题目描述:
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"
:
1 2 3 4 5 6 7 8
| 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"
.
1 2 3 4 5 6 7 8
| 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"
.
1 2 3 4 5 6 7 8
| 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.
看完这道题, 首先想到的是使用递归, 但是思维惯性让我觉得递归可能超时, 所以按照tag中的动态规划方法来做, 我是使用了三维数组来进行动态规划, 有四重循环, 所以可能还有优化空间. dp[i][j][k]
表示s1[i]和s2[j]开始的长度为k的子串是不是scramble的, 最后要返回的结果是dp[0][0][s1.length()]
, 所以i和j要从大到小遍历.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Solution { public: bool isScramble(string s1, string s2) { if(s1.length() != s2.length()) return false; int len = s1.length(); vector<vector<vector<int>>> dp(len, vector<vector<int>>(len, vector<int>(len + 1, 0))); for(int i = 0; i < len; i++){ for(int j = 0; j < len; j++){ if(s1[i] == s2[j]){ dp[i][j][1] = 1; } } } for(int i = len - 1; i >= 0; i--){ for(int j = len - 1; j >= 0; j--){ for(int k = 2; i + k <= len && j + k <= len; k++){ for(int r = 1; r < k && !dp[i][j][k]; r++){ dp[i][j][k] = (dp[i][j][r] && dp[i + r][j + r][k - r]) || (dp[i][j + k - r][r] && dp[i + r][j][k - r]); } } } }
return dp[0][0][len]; } };
|
但是这个方法速度并不是很理想, 比较快的方法反而是递归+剪枝, 在递归前先判断字符串中字母数量是不是相同, 如果不相同则可以直接返回false.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public: bool isScramble(string s1, string s2) { if(s1.length() != s2.length()) return false; return isScrambleImpl(s1, s2, 0, 0, s1.length()); } bool isScrambleImpl(string &s1, string &s2, int start1, int start2, int len){ vector<int> charTimes(26, 0); for(int i = start1; i < start1 + len; i++){ charTimes[s1[i] - 'a']++; } int flag = true; for(int i = start2; i < start2 + len; i++){ charTimes[s2[i] - 'a']--; if(charTimes[s2[i] - 'a'] < 0){ flag = false; break; } } if(!flag) return false; if(len == 1 && len == 1) return true; for(int i = 1; i < len; i++){ if((isScrambleImpl(s1, s2, start1, start2, i) && isScrambleImpl(s1, s2, start1 + i, start2 + i, len - i)) || (isScrambleImpl(s1, s2, start1, start2 + len - i, i) && isScrambleImpl(s1, s2, start1 + i, start2, len - i))){ return true; } } return false; } };
|