LeetCode 87. 扰乱字符串(C++)

题目描述

给定一个字符串 s1,我们可以把它递归地分割成两个非空子字符串,从而将其表示为二叉树。

下图是字符串 s1 = “great” 的一种可能的表示形式。

LeetCode 87. 扰乱字符串(C++)_第1张图片
在扰乱这个字符串的过程中,我们可以挑选任何一个非叶节点,然后交换它的两个子节点。

例如,如果我们挑选非叶节点 “gr” ,交换它的两个子节点,将会产生扰乱字符串 “rgeat” 。

LeetCode 87. 扰乱字符串(C++)_第2张图片
我们将 "rgeat” 称作 “great” 的一个扰乱字符串。

同样地,如果我们继续交换节点 “eat” 和 “at” 的子节点,将会产生另一个新的扰乱字符串 “rgtae” 。

LeetCode 87. 扰乱字符串(C++)_第3张图片
我们将 "rgtae” 称作 “great” 的一个扰乱字符串。

给出两个长度相等的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。

示例 1:

输入: s1 = “great”, s2 = “rgeat”
输出: true
示例 2:

输入: s1 = “abcde”, s2 = “caebd”
输出: false

思路

这道题定义了一种爬行字符串(扰乱字符串),就是说假如把一个字符串当做一个二叉树的根,然后它的非空子字符串是它的子节点,然后交换某个子字符串的两个子节点,重新爬行回去形成一个新的字符串,这个新字符串和原来的字符串互为爬行字符串。

这道题可以用递归Recursion或是动态规划Dynamic Programming来做,简单的说,**就是s1和s2是scramble的话,那么必然存在一个在s1上的长度l1,将s1分成s11和s12两段,同样有s21和s22.那么要么s11和s21是scramble的并且s12和s22是scramble的;要么s11和s22是scramble的并且s12和s21是scramble的。**就拿题目中的例子 rgeat 和 great 来说,rgeat 可分成 rg 和 eat 两段, great 可分成 gr 和 eat 两段,rg 和 gr 是scrambled的, eat 和 eat 当然是scrambled。根据这点,我们可以写出代码如下。

代码

class Solution {
     
public:
    bool isScramble(string s1, string s2) {
        //递归,可改进成动态规划
        if(s1==s2) return true;
        string str1=s1,str2=s2;
        sort(str1.begin(),str1.end());
        sort(str2.begin(),str2.end());
        if(str1!=str2) return false;
        for(int i=1;i<s1.size();i++)
        {
     
            string s11=s1.substr(0,i);
            string s12=s1.substr(i);
            string s21=s2.substr(0,i);
            string s22=s2.substr(i);
            if(isScramble(s11,s21) && isScramble(s12,s22)) return true;
            s21=s2.substr(s1.size()-i);
            s22=s2.substr(0,s1.size()-i);
            if(isScramble(s11,s21) && isScramble(s12,s22)) return true;
        }
        return false;
    }
};

你可能感兴趣的:(LeetCode 87. 扰乱字符串(C++))