您的位置:首页 > 其它

算法学习之动态规划(leetcode 87. Scramble String)

2017-04-08 15:48 603 查看
0x01题目

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":




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".




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".




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.


0x02解析

本题的目标是判断两个字符串之间的关系,正确的思路应该是使用遍历+分而治之的思想来做,若要判断两个字符串之间的关系,可以将两个字符串进行切割,判断切割后的子字符串之间的关系。

如果字符串s1[0, 1, … len-1]和s2[0, 1, …, len-1]满足scramble string条件(简称为SS条件),则有两种情况至少满足一种情况。

A. s1[0, 1, …i-1]和s2[0, 1, …i-1]满足SS条件且s1[i, len-1]和s2[i, len-1]满足SS条件

B. s1[0, 1, …i-1]和s2[len-i, len-1]满足SS条件且s1[i, len-1]和s2[0, 1, …len-i-1]满足SS条件

有两种解法:第一种递归,第二种动态规划,如代码所示。

0x03代码

解法一
public class Solution {
public boolean isScramble(String s1, String s2) {
if(s1.equals(s2)) return true;
if(s1.length() != s2.length()) return false;
int len = s1.length();

int[] letters = new int[26];
for(int i = 0; i < len; i++){
letters[s1.charAt(i) - 'a']++;
letters[s2.charAt(i) - 'a']--;
}

for(int i = 0; i < 26; i++){
if(letters[i] != 0){
return false;
}
}

for(int i = 1; i < len; i++){
if(isScramble(s1.substring(0, i), s2.substring(0, i))
&&
isScramble(s1.substring(i), s2.substring(i))
){
return true;
}
if(isScramble(s1.substring(0, i), s2.substring(len - i))
&&
isScramble(s1.substring(i), s2.substring(0, len - i))
){
return true;
}
}

return false;
}
}


解法二
/*
定义F(i, j, k)为S1[i..i + k - 1]和S2[j..j + k - 1]是否满足SS条件。
则需要遍历所有情况检查F(i, j, k)是否为真
S1 [   x1    |         x2         ]
i         i + q                i + k - 1
有以下两种可能性
S2 [   y1    |         y2         ]
j         j + q                j + k - 1
或者
S2 [       y1        |     y2     ]
j                 j + k - q    j + k - 1
所以,当1 <= q < k时候,
F(i, j, k) = (
F(i, j, q) AND F(i + q, j + q, k - q))
OR
F(i, j + k - q, q) AND F(i + q, j, k - q)
)
当k = 1时
F(i, j, k) = (s1.charAt(i) == s2.charAt(j));
*/
public class Solution {
public boolean isScramble(String s1, String s2) {
if (s1.length() != s2.length()) return false;
int len = s1.length();

boolean [][][] F = new boolean[len][len][len + 1];
for (int k = 1; k <= len; ++k)
for (int i = 0; i + k <= len; ++i)
for (int j = 0; j + k <= len; ++j)
if (k == 1)
F[i][j][k] = (s1.charAt(i) == s2.charAt(j));
else for (int q = 1; q < k && !F[i][j][k]; ++q) {
F[i][j][k] = (
F[i][j][q] && F[i + q][j + q][k - q])
||
(F[i][j + k - q][q] && F[i + q][j][k - q]);
}
return F[0][0][len];
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息