interleaving string

题目描述:

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.

最直观的做法,定义一个三维的状态数组 f[ k ] [ i ] [ j ] 表示s3[0 ... k-1] 是 s1[0 ... i ] 和 s2[0 ... j ]交错而成。

那么状态式定义为:

f[ k ] [ i ] [ j ]     =    ( f [ k-1 ] [i ] [ j - 1]  && s2[ j-1] == s3  [ k -1]  // s2的第j-1个字符与s3的第k-1个字符匹配。

或者是            =    ( f [ k-1 ] [ i-1 ] [ j ]  && s1 [ i-1] == s3  [ k -1]  // s1的第i-1个字符与s3的第k-1个字符匹配。

两者只要有一个满足条件即可。

代码如下:

Version 1:  时间复杂度 O(n^3),空间复杂度 O(n^3).Time : ~200ms

    bool isInterleave(string s1, string s2, string s3) {
        const int n1 = s1.size(), n2= s2.size(), n3 = s3.size();
        if(n1==0) return s2==s3;
        if(n2==0) return s1==s3;
        bool f[n3+1][n1+1][n2+1];
        fill_n(&f[0][0][0], (n3+1)*(n1+1)*(n2+1),false);
        
        f[0][0][0]=true;
        
        //k i j !!
        //i==0
        for(int j = 1 ; j <= n2;++j)
        {
            f[j][0][j] = f[j-1][0][j-1] && s2[j-1]==s3[j-1];
        }
        //j==0
        for(int i = 1 ; i <= n1;++i)
        {
            f[i][i][0] = f[i-1][i-1][0] && s1[i-1]==s3[i-1];
        }        
        
        for(int k=1;k<=n3;++k)
        {
            for(int i=1;i<=n1;++i)
            {
                for(int j=1;j<=n2;++j)
                {
                    f[k][i][j] = (f[k-1][i-1][j] && s1[i-1]==s3[k-1]) || (f[k-1][i][j-1] && s2[j-1]==s3[k-1]);
                }
            }
        }
        return f[n3][n1][n2];
    }

Version 2:  时间复杂度 O(n^2),空间复杂度 O(n^2).Time :~ 4ms

    bool isInterleave(string s1, string s2, string s3) {
        const int n1 = s1.size(), n2= s2.size(), n3 = s3.size();
        if(n1 + n2 < n3) return false;
        
        if(n1==0) return s2==s3;
        if(n2==0) return s1==s3;
        
        bool f[n1+1][n2+1];
        fill_n(&f[0][0], (n1+1)*(n2+1), false);
        
        //initialize
        f[0][0] = true;
        //n1.size() <= n3.size() ,否则在前面就自动return false.
        for(int i = 1; i < n1+1; ++i)
            //f[i][0] = (s1.substr(0,i) == s3.substr(0,i));
            f[i][0] = f[i-1][0] && s1[i-1] == s3[i-1];
        for(int j = 1; j< n2+1; ++j)
            //f[0][j] = (s2.substr(0,j) == s3.substr(0,j));
            f[0][j] = f[0][j-1] && s2[j-1] == s3[j-1];
        
        for(int i = 1; i <= n1;++i)
            for(int j=1;j<=n2;++j)
                f[i][j] = ((f[i-1][j] && s1[i-1] == s3[i+j-1])  || (f[i][j-1] && s2[j-1] == s3[i+j-1]) );
        return f[n1][n2];
    }

Version 3:  时间复杂度 O(n^2),空间复杂度 O(n). Time :~ 4ms

使用滚动数组来解决:

bool isInterleave(string s1, string s2, string s3) {
        const int n1 = s1.size(), n2= s2.size(), n3 = s3.size();
        if(n1 + n2 < n3) return false;
        
        if(n1==0) return s2==s3;
        if(n2==0) return s1==s3;
        
        //进一步降低空间复杂度为O(min(n1,n2))
        
        bool f[n1+1];
        fill_n(&f[0],n1+1,false);
        
        f[0]=true;
        
        //first row
        for(int i = 1 ; i <= n1; ++i)
            f[i] = f[i-1]&&(s1[i-1]==s3[i-1]); //never out of range!! for n1 <= n3
            
        //column 0 has completed
        //n2 cycles
        for(int times = 1; times <= n2; ++times)
        {
            //update row
            //specially process the first element
            f[0] = (s2[times-1] == s3[times-1] && f[0]);
            
            for(int i = 1;i <= n1;++i)
            {
                f[i] = ( f[i] && s2[times-1]==s3[i+times-1]) || (f[i-1] && s1[i-1]==s3[i+times-1]);
            }
        }
        return f[n1];
        
    }




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值