原题链接: http://oj.leetcode.com/problems/scramble-string/ 

这道题看起来是比較复杂的,假设用brute force,每次做分割,然后递归求解,是一个非多项式的复杂度,一般来说这不是面试官想要的答案。

这事实上是一道三维动态规划的题目,我们提出维护量res[i][j][n],当中i是s1的起始字符,j是s2的起始字符,而n是当前的字符串长度,res[i][j][len]表示的是以i和j分别为s1和s2起点的长度为len的字符串是不是互为scramble。

有了维护量我们接下来看看递推式,也就是怎么依据历史信息来得到res[i][j][len]。推断这个是不是满足,事实上我们首先是把当前s1[i...i+len-1]字符串劈一刀分成两部分,然后分两种情况:第一种是左边和s2[j...j+len-1]左边部分是不是scramble,以及右边和s2[j...j+len-1]右边部分是不是scramble;另外一种情况是左边和s2[j...j+len-1]右边部分是不是scramble,以及右边和s2[j...j+len-1]左边部分是不是scramble。假设以上两种情况有一种成立,说明s1[i...i+len-1]和s2[j...j+len-1]是scramble的。而对于推断这些左右部分是不是scramble我们是有历史信息的,由于长度小于n的全部情况我们都在前面求解过了(也就是长度是最外层循环)。

上面说的是劈一刀的情况,对于s1[i...i+len-1]我们有len-1种劈法,在这些劈法中仅仅要有一种成立,那么两个串就是scramble的。

总结起来递推式是res[i][j][len] = || (res[i][j][k]&&res[i+k][j+k][len-k] || res[i][j+len-k][k]&&res[i+k][j][len-k]) 对于全部1<=k<len,也就是对于全部len-1种劈法的结果求或运算。由于信息都是计算过的,对于每种劈法仅仅须要常量操作就可以完毕,因此求解递推式是须要O(len)(由于len-1种劈法)。

如此总时间复杂度由于是三维动态规划,须要三层循环,加上每一步须要线行时间求解递推式,所以是O(n^4)。尽管已经比較高了,可是至少不是指数量级的,动态规划还是有非常大有事的,空间复杂度是O(n^3)。代码例如以下:

public boolean isScramble(String s1, String s2) {
if(s1==null || s2==null || s1.length()!=s2.length())
return false;
if(s1.length()==0)
return true;
boolean[][][] res = new boolean[s1.length()][s2.length()][s1.length()+1];
for(int i=0;i<s1.length();i++)
{
for(int j=0;j<s2.length();j++)
{
res[i][j][1] = s1.charAt(i)==s2.charAt(j);
}
}
for(int len=2;len<=s1.length();len++)
{
for(int i=0;i<s1.length()-len+1;i++)
{
for(int j=0;j<s2.length()-len+1;j++)
{
for(int k=1;k<len;k++)
{
res[i][j][len] |= res[i][j][k]&&res[i+k][j+k][len-k] || res[i][j+len-k][k]&&res[i+k][j][len-k];
}
}
}
}
return res[0][0][s1.length()];
}

个人认为这是LeetCode中最难的动态规划的题目了,要进行一次三维动态规划,对于维护量的含义也比較讲究。有朋友会讨论这个维护量是怎么提出来的,我自己也没什么绝对的方法,还是熟能生巧,靠“感觉”,做的题目多了就自然来了,这个做高中数学题有点类似哈,辅助线是靠“灵感”的哈。面试中假设遇到就是top难度的了,只是即使如此,仅仅要思路清晰,还是能够记住的。假设没做过,个人认为比較难当场想出来,只是算法大牛就另说了,这样的题非常常常出如今编程比赛中,ACM高手还是不在话下的哈。

Scramble String -- LeetCode的更多相关文章

  1. Scramble String leetcode java

    题目: Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty subs ...

  2. 【一天一道LeetCode】#87. Scramble String

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

  3. Leetcode:Scramble String 解题报告

    Scramble String Given a string s1, we may represent it as a binary tree by partitioning it to two no ...

  4. 【leetcode】Scramble String

    Scramble String Given a string s1, we may represent it as a binary tree by partitioning it to two no ...

  5. 【LeetCode练习题】Scramble String

    Scramble String Given a string s1, we may represent it as a binary tree by partitioning it to two no ...

  6. [leetcode]87. Scramble String字符串树形颠倒匹配

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  7. [LeetCode] Scramble String -- 三维动态规划的范例

    (Version 0.0) 作为一个小弱,这个题目是我第一次碰到三维的动态规划.在自己做的时候意识到了所谓的scramble实际上有两种可能的类型,一类是在较低层的节点进行的两个子节点的对调,这样的情 ...

  8. [leetcode] 87. Scramble String (Hard)

    题意: 判断两个字符串是否互为Scramble字符串,而互为Scramble字符串的定义: 字符串看作是父节点,从字符串某一处切开,生成的两个子串分别是父串的左右子树,再对切开生成的两个子串继续切开, ...

  9. [LintCode] Scramble String 爬行字符串

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

随机推荐

  1. invalid byte sequence for encoding "UTF8": 0xe99d2c

    服务器还原数据库数据出错,老规矩... 字符集编码的问题 http://blog.csdn.net/beiigang/article/details/39582583 over....

  2. AdvStringGrid 标题头

    标题头内容: 字体: 标题头高度: 头的对齐方式:

  3. mybatis中多条件判断---choose when的用法

    <select id="getFunctionByPage" resultMap="FunctionRlt"> SELECT K.FUNCTION_ ...

  4. Jenkins+Docker持续集成

    本节内容: Jenkins介绍 安装部署Jenkins Jenkins构建maven风格的job Jenkins邮件通知设置 Sonar Jenkins与Docker结合 一.Jenkins介绍 Je ...

  5. JavaScript中的数据结构及实战系列

    本系列主要是讲解JavaScript中的数据结构及在实际项目中遇到的地方 JavaScript中的数据结构及实战系列(1):队列 JavaScript中的数据结构及实战系列(2):栈

  6. 2018 ACM-ICPC, Syrian Collegiate Programming Contest F - Pretests SOS dp

    #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk mak ...

  7. HDU - 4458 计算几何判断点是否在多边形内

    思路:将飞机看成不动的,然后枚举时间看点是否在多边形内部. #include<bits/stdc++.h> #define LL long long #define fi first #d ...

  8. vim选中多行复制粘贴

    1.按v进入可视模式,移动光标选中需要复制的行: 2.使用y复制选中块到缓冲区(剪切选中块使用d): 3.将光标移动到粘贴的位置,按p即可. 复制多行并粘贴到指定位置后,可能需要进行多行缩进.多行缩进 ...

  9. Jenkins的Pipeline脚本在美团餐饮SaaS中的实践

    一.背景 在日常开发中,我们经常会有发布需求,而且还会遇到各种环境,比如:线上环境(Online),模拟环境(Staging),开发环境(Dev)等.最简单的就是手动构建.上传服务器,但这种方式太过于 ...

  10. myeclipse 插件下载方式

    myeclipse10,大家都知道,MyEclipse 中有一个烦人的 Software and Workspace center,这东西,加载特别慢,我用10版本基本是没有可能看到这个界面.更别说在 ...