题目传送地址:https://leetcode.cn/problems/scramble-string/
运行效率:
代码如下:
class Solution {
String s1;
String s2;
int[][][] dp;
public boolean isScramble(String s1, String s2) {
int s1Length = s1.length();
int s2Length = s2.length();
if (s1Length != s2Length) {
return false;
}
//下面之所以要+1的原因, 是因为后面我们会用到 dp[i][j][length] 避免越界的情况产生
int[][][] dp = new int[s1Length][s1Length][s1Length + 1];
this.s1 = s1;
this.s2 = s2;
this.dp = dp;
boolean df = df(0, 0, s1Length);
return df;
}
// 第一个字符串从 i1 开始,第二个字符串从 i2 开始,子串的长度为 length,是否和谐s
public boolean df(int i, int j, int length) {
//如果dp[i][j][length]曾经被计算过了,那就直接用就行
if (dp[i][j][length] != 0) {
return dp[i][j][length] == 1;
}
String substring1 = this.s1.substring(i, i + length);
String substring2 = this.s2.substring(j, j + length);
//处理边界情况
if (substring1.equals(substring2)) {
dp[i][j][length] = 1;
return true;
}
if (!checkIfSimilar(substring1, substring2)) {
dp[i][j][length] = -1;
return false;
}
//n是分割线
for (int n = 1; n < length; n++) {
//不交换 的情况
boolean df1 = df(i, j, n);
boolean df2 = df(i + n, j + n, length - n);
if (df1 && df2) {
dp[i][j][length] = 1;
return true;
}
//交换 的情况
boolean df3 = df(i, j + length - n, n);//s1前半段和s2后半段做对比
boolean df4 = df(i + n, j, length - n); //s1后半段和s2前半段做对比
if (df3 && df4) {
dp[i][j][length] = 1;
return true;
}
}
dp[i][j][length] = -1;
return false;
}
/**
* 校验两个字符串里的各字符数目是否一致
*
* @param s1
* @param s2
* @return
*/
public static boolean checkIfSimilar(String s1, String s2) {
HashMap<Character, Integer> map = new HashMap<>();
for (int i = 0; i < s1.length(); i++) {
char c = s1.charAt(i);
if (map.containsKey(c)) {
Integer integer = map.get(c);
map.put(c, integer + 1);
} else {
map.put(c, 1);
}
}
for (int j = 0; j < s2.length(); j++) {
char c = s2.charAt(j);
if (map.containsKey(c)) {
Integer integer = map.get(c);
map.put(c, integer - 1);
} else {
return false;
}
}
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
if (entry.getValue() != 0) {
return false;
}
}
return true;
}
}