题目:交叉字符串

来源:互联网 发布:暴雪降至 知乎 编辑:程序博客网 时间:2024/05/16 12:23

给出三个字符串: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()];    }} 


0 0