给出三个字符串:s1、s2、s3,判断s3是否由s1和s2交叉构成。您在真实的面试中是否遇到过这个题?
Yes
样例
比如 s1 = "aabcc" s2 = "dbbca"
- 当 s3 = "aadbbcbcac",返回 true.
- 当 s3 = "aadbbbaccc", 返回 false.
挑战
要求时间复杂度为O(n^2)或者更好
标签 Expand
相关题目 Expand
解题思路:
用3个指针分别指向s1,s2,s3。
比如 i 指向 S1 ,j 指向 S2,k 指向 S3。
从k=s0开始去匹配S1,S2。也分别从i=0,j=0,若i,j都匹配则有2种情况用i匹配或者j匹配递归实现,只有一个匹配时,直接匹配后再去匹配剩下的。不匹配返回false。此时空间时间复杂度较大
public class Solution {
/**
* Determine whether s3 is formed by interleaving of s1 and s2.
* @param s1, s2, s3: As description.
* @return: true or false.
*/
public boolean isInterleave(String s1, String s2, String s3) {
// write your code here
if(s3.length()!=s2.length()+s1.length()) return false;
if(null==s1||0==s1.length()){
if(s2.equals(s3)){
return true;
}else{
return false;
}
}
if(null==s2||0==s2.length()){
if(s1.equals(s3)){
return true;
}else{
return false;
}
}
int i = 0;
int j = 0;
for(int k=0;k<s3.length();k++){
boolean s1flag = false;
boolean s2flag = false;
if(i<s1.length()&&s1.charAt(i)==s3.charAt(k)){
s1flag = true;
}
if(j<s2.length()&&s2.charAt(j)==s3.charAt(k)){
s2flag = true;
}
if(!s1flag&&!s2flag){
return false;
}else if(s1flag&&s2flag){
return isInterleave(s1.substring(i+1), s2.substring(j), s3.substring(k+1))||isInterleave(s1.substring(i), s2.substring(j+1), s3.substring(k+1));
}else if(s1flag){
i++;
}else{
j++;
}
}
return true;
}
}
动态规划实现,减少重复的计算
为了减少重复计算,就要使用动态规划来记录中间结果。
这里我使用了一个二维数组result[i][j]来表示s1的前i个字符和s2的前j个字符是否能和s3的前i+j个字符匹配。 状态转移方程如下: result[i,j] = (result[i-1,j] && s1[i] = s3[i+j]) || (result[i,j-1] && s2[j] = s3[i+j]); 其中0≤i≤len(s1) ,0≤j≤len(s2) 这样算法复杂度就会下降到O(l1*l2) |
public class Solution {
/**
* Determine whether s3 is formed by interleaving of s1 and s2.
* @param s1, s2, s3: As description.
* @return: true or false.
*/
public boolean isInterleave(String s1, String s2, String s3) {
// write your code here
if(s3.length()!=s2.length()+s1.length()) return false;
if(null==s1||0==s1.length()){
if(s2.equals(s3)){
return true;
}else{
return false;
}
}
if(null==s2||0==s2.length()){
if(s1.equals(s3)){
return true;
}else{
return false;
}
}
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
char[] c3 = s3.toCharArray();
boolean a[][] = new boolean[c1.length+1][c2.length+1];
for(int i=0;i<c1.length;i++){
if(c1[i]==c3[i]){
a[i+1][0] = true;
}else {
break;
}
}
for(int i=0;i<c2.length;i++){
if(c2[i]==c3[i]){
a[0][i+1] = true;
}else {
break;
}
}
for(int i=1;i<=c1.length;i++){
for(int j=1;j<=c2.length;j++){
char ci = c1[i-1];
char cj = c2[j-1];
char ck = c3[i+j-1];
a[i][j] = (a[i-1][j]&&ci==ck)||(a[i][j-1]&&cj==ck);
}
}
return a[s1.length()][s2.length()];
}
}