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.

Example 1:

Input: s1 = "great", s2 = "rgeat"
Output: true

Example 2:

Input: s1 = "abcde", s2 = "caebd"
Output: false

思路:对付复杂问题的方法是从简单的特例来思考。简单情况:

  1. 如果字符串长度为1,那么必须两个字符串完全相同;
  2. 如果字符串长度为2,例如s1='ab',则s2='ab'或s2='ba'才行
  3. 如果字符串任意长度,那么可以把s1分为a1, b1两部分,s2分为a2,b2两部分。需要满足:((a1=a2)&&(b1=b2)) || ((a1=b2)&&(a2=b1)) =>可用递归
class Solution {
public boolean isScramble(String s1, String s2) {
if(s1.length()==1) return s1.equals(s2); String s11;
String s12;
String s21;
String s22;
for(int i = 1; i <= s1.length(); i++){
s11 = s1.substring(0, i);
s12 = s1.substring(i);
s21 = s2.substring(0,i);
s22 = s2.substring(i);
if(isScramble(s11,s21) && isScramble(s12,s22)) return true;
if(isScramble(s11,s22) && isScramble(s12,s21)) return true;
}
return false;
}
}

Result: Time Limit Exceeded

解决方法:动态规划。三维状态dp[i][j][k],前两维分别表示s1和s2的下标起始位置,k表示子串的长度。dp[i][j][k]=true表示s1(i, i+k-1)和s2(j, j+k-1)是scramble。

结合递归法中的逻辑,dp[i][j][k]=true的条件是s1(i, i+split-1)=s2(j, j+split-1) && s1(i+split, i+k-1) = s2(j+split, j+k-1) 或者 s1(i, i+split-1)=s2(j+k-split, j+k-1) && s1(i+split, i+k-1) = s2(j, j+k-split-1)

所以状态转移方程是:如果dp[i][j][split] = true && dp[i+split][j+split][k-split] = true 或者 dp[i][j+k-split][split]=true && dp[i+split][j][k-split]=true,那么dp[i][j][k]=true

初始状态:当k=1的时候dp[i][j][1]=true的条件是s1(i)=s2(j)

class Solution {
public boolean isScramble(String s1, String s2) {
if(s1.length()== 0 || s1.equals(s2)) return true; boolean dp[][][] = new boolean[s1.length()][s1.length()][s1.length()+1]; //initial state
for(int i = 0; i < s1.length(); i++){
for(int j = 0; j < s2.length(); j++){
dp[i][j][1] = s1.charAt(i)==s2.charAt(j);
}
} //state transfer
for(int k = 2; k <= s1.length(); k++){
for(int i = 0; i+k-1 < s1.length(); i++){
for(int j = 0; j+k-1 < s1.length(); j++){
for(int split = 1; split < k; split++){
//如果dp[i][j][split] = true && dp[i+split][j+split][k-split] = true 或者 dp[i][j+k-split][split]=true && dp[i+split][j][k-split]=true,那么dp[i][j][k]=true
if((dp[i][j][split] && dp[i+split][j+split][k-split]) || (dp[i][j+k-split][split] && dp[i+split][j][k-split])){
dp[i][j][k] = true;
break;
}
}
}
}
}
return dp[0][0][s1.length()];
}
}

最新文章

  1. YII 2.x 模板文件的 beginBlock、beginContent、beginCache
  2. //给定N个整数序列{A1,A2,A3...An},求函数f(i,j)=(k=i~j)Ak的求和
  3. linux下共享库的注意点之-fpic
  4. C和指针 第十章 结构和联合 (一)
  5. Python格式化字符串和转义字符
  6. Java集合源码分析(七)HashMap&lt;K, V&gt;
  7. WDS的原理
  8. USB硬件远程共享解决iphone已停用
  9. HDU 2795 (线段树 单点更新) Billboard
  10. 菱形实现气泡Bubble,菱形画箭头,菱形画三角形
  11. boost 1.56.0 编译
  12. PHP中抽象类与接口的应用场景
  13. 51nod贪心算法教程
  14. 手机自动化培训:Appium介绍
  15. Sql语句备份Sqlserver数据库
  16. js常见算法(一)
  17. [福大软工教学] W班 第1次成绩排行榜
  18. vue+mint-ui的微博页面(支持评论@添加表情等)
  19. delete 和 delete [] 的真正区别
  20. Windows下dos命令行

热门文章

  1. json-lib json反序列化——日期转换
  2. html页面元素命名参考
  3. LC 963. Minimum Area Rectangle II
  4. View的事件机制
  5. 客户端服务器通讯常用的一种方法——Marshal类
  6. UISearchBar去掉SearchBar上面两条分割线
  7. 重启 hdfs and yarn datanode
  8. .net代码混淆 .NET Reactor 研究 脚本一键混淆一键发布
  9. SSO单点登录统一身份认证系统
  10. web开发常识