题目:交叉字符串


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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值