Leetcode_scramble-string

本文详细解析了如何通过递归和分治策略解决LeetCode中的字符串乱序问题,包括排序剪枝技巧和复杂代码实现。文章还提供了参考代码,帮助读者深入理解并解决类似问题。

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.youkuaiyun.com/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);
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值