您的位置:首页 > 其它

个人记录-LeetCode 97. Interleaving String

2017-04-12 20:00 399 查看
问题:

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

For example,

Given:

s1 = “aabcc”,

s2 = “dbbca”,

When s3 = “aadbbcbcac”, return true.

When s3 = “aadbbbaccc”, return false.

题目的含义是:

有两个字符串s1和s2,每次从这两个字符串的一个中,取出一个字符(从前往后取),

添加到新的字符串中,直到两个字符串都取完。

显然,由于每次都可以随机选取,因此最终可能生成许多不同的新字符串。

现在,需要判断s3是否为这些生成的新字符串中的一个。

代码示例:

1、比较容易想到的是,暴力递归,虽然可行,但会超时。

public class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
//首先保证s1、s2的长度和等于s3的长度, 在innerHelper中完成递归 (假设s1、s2和s3不为null)
return (s1.length() + s2.length() == s3.length()) && innerHelper(s1, s2, s3);
}

private boolean innerHelper(String s1, String s2, String s3) {
int len1 = s1.length();
int len2 = s2.length();
int len3 = s3.length();

if (len1 == 0 && len2 == 0 && len3 == 0) {
return true;
}

char temp = s3.charAt(0);

String s1Sub = len1 > 1 ? s1.substring(1) : "";
String s2Sub = len2 > 1 ? s2.substring(1) : "";
String s3Sub = len3 > 1 ? s3.substring(1) : "";

//这里的思路主要是,从s3中取出第一个字符
//判断这个字符是否与s1、s2的首位相等
//如果相等,就接着比较子串
//最终,没有子串可继续比较时,就说明s3为Interleaving String
if (len1 > 0 && len2 > 0) {
if(s1.charAt(0) == temp && s2.charAt(0) == temp) {
return innerHelper(s1Sub, s2, s3Sub) || innerHelper(s1, s2Sub, s3Sub);
} else if (s1.charAt(0) == temp) {
return innerHelper(s1Sub, s2, s3Sub);
} else if (s2.charAt(0) == temp) {
return innerHelper(s1, s2Sub, s3Sub);
}
} else if (len1 == 0 && len2 > 0) {
return (s2.charAt(0) == temp) && innerHelper(s1, s2Sub, s3Sub);
} else if (len1 > 0 && len2 == 0){
return (s1.charAt(0) == temp) && innerHelper(s1Sub, s2, s3Sub);
}

return false;
}
}


2、DP

LeetCode中,字符串的比对,基本上都需要靠DP才能解决。

public class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
//同样,首先保证长度符合条件
if (s1.length() + s2.length() != s3.length()) {
return false;
}

int n1 = s1.length();
int n2 = s2.length();

//定义dp数组,dp[i][j]表示s3中(i+j)长度的子串
//是否为由s1中i长度,s2中j长度子串构成的Interleaving串
boolean[][] dp = new boolean[n1+1][n2+1];

//当i,j均为0时,s3长度也为0,于是值为true
dp[0][0] = true;

//当j为0时,即s2长度为0,那么s3必须完全与s1相等,才能成为Interleaving串
for (int i = 1; i <= n1; ++i) {
//此时,dp[i][0]由截至前一位的值,与当前位的匹配情况来决定
dp[i][0] = dp[i-1][0] && (s1.charAt(i - 1) == s3.charAt(i - 1));
}

//同理,当i为0时,即s1长度为0,那么s3必须完全与s2相等,才能成为Interleaving串
for (int j = 1; j <= n2; ++j) {
dp[0][j] = dp[0][j-1] && (s2.charAt(j-1) == s3.charAt(j-1));
}

//至此,dp数组的两条边已经确定完毕

for (int i = 1; i <= n1; ++i) {
for (int j = 1; j <= n2; ++j) {
//现在来定义递推公式
//如果s3中的(i+j)位是从s1中取出的,那么dp[i][j]的值由dp[i-1][j]、及s1中的第i位,s3中的i+j位决定
dp[i][j] = (dp[i-1][j] && s1.charAt(i - 1) == s3.charAt(i - 1 + j))
//如果s3中的(i+j)位是从s2中取出的,那么那么dp[i][j]的值由dp[i][j-1]、及s2中的第j位,s3中的i+j位决定
|| (dp[i][j-1] && s2.charAt(j - 1) == s3.charAt(j - 1 + i));
}
}

//dp[n1][n2]保存的就是完整长度的字符串的匹配情况
return dp[n1][n2];
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: