Leetcode_scramble-string

来源:互联网 发布:snk mac 模拟器 编辑:程序博客网 时间:2024/05/16 11:00
地址:https://oj.leetcode.com/problems/scramble-string/

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.

Below is one possible representation of s1 = "great":

    great   /    \  gr    eat / \    /  \g   r  e   at           / \          a   t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".

    rgeat   /    \  rg    eat / \    /  \r   g  e   at           / \          a   t

We say that "rgeat" is a scrambled string of "great".

Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".

    rgtae   /    \  rg    tae / \    /  \r   g  ta  e       / \      t   a

We say that "rgtae" is a scrambled string of "great".

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

思路:这道题是笔者Leetcode第一刷的最后一题,因为看上去根本没有思路,请原谅笔者的渣水平。参考其他的解题报告后,对这题才有比较深入一点的理解。其实就和二叉树本身的递归定义一样,这题应该是分治+递归, 既然能用二叉树表示,就能转化为判断左右子树是否同样是scramble string.
比如判断s1和s2是否是scramble string, 将
s1分为left1, right1, s2分为left2和right2两个子串,其中left1和left2长度相同,判断left1, left2 的pair 和 right1, right2的pair是否均为scramble string, 是的话直接返回true
不然再将left1,right1重新赋为长度各为之前的子串,即left1和right2长度相同,left2与right1长度相同,这种情况是针对两层子树都翻转的情况,举个栗子,
比如1234,正常是分成了12和34,swap后分成了34和12,其中34,12再分别swap一下,就分成了4, 3, 2, 1,这样的情况就是1234的前两个与“4,3,2,1”的后两个判断是否是scramble string, 1234的后两个与“4,3,2,1”的前两个判断。

如果没有找到,继续把所有不同分割情况都遍历。

参考了两份解题报告,有了别人思路上的提携,再加上自己的理解,就好做多了:
http://blog.csdn.net/fightforyourdream/article/details/17707187
http://www.cnblogs.com/TenosDoIt/p/3452004.html

注意要先排个序做剪枝(也可以自己开256数组做桶排序), 不然递归深度太多会TLE. 
参考代码:
class Solution {public:    bool subscramble(string s1, string s2)    {        if(s1==s2)            return true;        string left1 = s1, left2 = s2, right1, right2;        sort(left1.begin(), left1.end());        sort(left2.begin(), left2.end());        if(left1 != left2)            return false;        for(int i = 1; i<s1.length(); ++i)        {            left1 = s1.substr(0, i);            left2 = s1.substr(i);            right1 = s2.substr(0, i);            right2 = s2.substr(i);            if(subscramble(left1, right1) && subscramble(left2, right2))                return true;            left1 = s1.substr(0, s1.length()-i);            left2 = s1.substr(s1.length()-i);            if(subscramble(left1, right2) && subscramble(left2, right1))                return true;        }        return false;    }    bool isScramble(string s1, string s2) {        return subscramble(s1, s2);    }};


0 0