[LeetCode]87. 扰乱字符串(java实现)动态规划
1. 题目
2. 读题(需要重点注意的东西)
思路一(闫式dp分析法):
f[i,j,k] 表示的是能否将长度为 k 的字符串 S1[i,i+k-1] 通过一些操作(分割+交换)转换为 长度为 S2[j,j+k-1] 的字符串,是一个 boolean 值。
思路二(递归):
注: 递归解法现在已经超时了
,其时间复杂度为O(5^n^)
假设字符串的长度是n,遍历所有可能的分割情况,将s1分割成[0, i) [i, n)
,s2由于可能翻转,所以可能是[0, i)和[i, n)
也可能是[n - i, n)和[0, n - i)
;分段比较长度相同的字符串,将它们进行排序,若相同的话,则排序后的字符串是相同的,考虑翻转与否两种情况:
-
不进行翻转:
isScramble(s1.substring(0, i), s2.substring(0, i)) && isScramble(s1.substring(i, n), s2.substring(i, n))
-
进行翻转:
isScramble(s1.substring(0, i), s2.substring(n - i, n))
&& isScramble(s1.substring(i, n), s2.substring(0, n - i))
不断递归在不同点处进行分割的子串,直到s1 == s2,返回true。
3. 解法
---------------------------------------------------解法1:dp---------------------------------------------------
class Solution {
public boolean isScramble(String s1, String s2) {
int n = s1.length();
boolean[][][] f = new boolean[n][n][n+1];
for (int k = 1; k <= n; k ++ )
for (int i = 0; i + k - 1 < n; i ++ )
for (int j = 0; j + k - 1 < n; j ++ ) {
if (k == 1) {
if (s1.charAt(i) == s2.charAt(j)) f[i][j][k] = true;
} else {
for (int u = 1; u < k; u ++ ) {
if (f[i][j][u] && f[i + u][j + u][k - u] || f[i][j + k - u][u] && f[i + u][j][k - u]) {
f[i][j][k] = true;
break;
}
}
}
}
return f[0][0][n];
}
}
可能存在的问题:
---------------------------------------------------解法2:递归--------------------------------------------------
class Solution {
public String sort(String s1){
char[] str = s1.toCharArray();
Arrays.sort(str);
return String.valueOf(str);
}
public boolean isScramble(String s1, String s2) {
if(s1.equals(s2)) return true;
if(!sort(s1).equals(sort(s2))) return false;
int n = s1.length();
for(int i = 1;i <= n - 1;i++){
if(isScramble(s1.substring(0, i), s2.substring(0, i))&& isScramble(s1.substring(i, n), s2.substring(i, n))) return true;
if(isScramble(s1.substring(0, i), s2.substring(n - i, n))&& isScramble(s1.substring(i, n), s2.substring(0, n - i))) return true;
}
return false;
}
}
可能存在的问题:
注意: String对象的比较需要使用equals(),不能直接使用==,详见java:String使用equals和==比较的区别
4. 可能有帮助的前置习题
5. 所用到的数据结构与算法思想
- dp
- dfs