LeetCode 扰乱字符串

给定一个字符串 s1,我们可以把它递归地分割成两个非空子字符串,从而将其表示为二叉树。
下图是字符串 s1 = “great” 的一种可能的表示形式。

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

在扰乱这个字符串的过程中,我们可以挑选任何一个非叶节点,然后交换它的两个子节点。
例如,如果我们挑选非叶节点 “gr” ,交换它的两个子节点,将会产生扰乱字符串 “rgeat” 。

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

我们将 "rgeat” 称作 “great” 的一个扰乱字符串。
同样地,如果我们继续将其节点 “eat” 和 “at” 进行交换,将会产生另一个新的扰乱字符串 “rgtae” 。

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

我们将 "rgtae” 称作 “great” 的一个扰乱字符串。
给出两个长度相等的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。

示例 1:

输入: s1 = "great", s2 = "rgeat"
输出: true

示例 2:

输入: s1 = "abcde", s2 = "caebd"
输出: false

思路分析:由于s1二叉树的构成有成很多种,并且**“可以挑选任何一个非叶节点,然后交换它的两个子节点”**,所以对于扰乱点比较难以确定。对于二叉树的构成多样主要是左、右子树的分法多种,我们可以使用一个for循环,对左右子树分法进行穷举。对于扰乱点的确定,我们可以在确定了分法进行递归匹配。

class Solution {
public:
	bool isScramble(string &s1, string &s2) {
		if (s1 == s2){
			return true;
		}
		if (s1.size() != s1.size()){
			return false;
		}
		int strSize = s1.size();
		vector character(26, 0);//用于判断s1包含的字母与s2包含的字母是否相同
		for (int i = 0; i < strSize; ++i){//统计s1、s2串中各个字母出现的次数
			++character[s1[i] - 'a'];//s1的字母计正
			--character[s2[i] - 'a'];//s2字母计负
		}
		for (int i = 0; i < 26; ++i){//判断是否有字母出现的次数不为零
			if (character[i] != 0){
				return false;
			}
		}
        //对分叉点进行穷举
		for (int i = 1; i < strSize; i++){
			string lefts1 = s1.substr(0, i), rights1 = s1.substr(i);//s1串分成(A,B)
			string lefts2 = s2.substr(0, i), rights2 = s2.substr(i);//s2串分成(A,B)
			//s1串(A,B)尝试匹配 s2(A,B)
			if (isScramble(lefts1, lefts2) && isScramble(rights1, rights2)){
				return true;
			}
			lefts2 = s2.substr(s1.length() - i);//s2串分成(B,A)
			rights2 = s2.substr(0, strSize - i);
			//s1串(A,B)尝试匹配 s2(B,A)
			if (isScramble(lefts1, lefts2) && isScramble(rights1, rights2)){
				return true;
			}
		}
		return false;
	}
};

LeetCode 扰乱字符串_第1张图片

你可能感兴趣的:(LeetCode)