【LeetCode】Interleaving String

参考链接

http://www.blogjava.net/sandy/archive/2013/05/10/398754.html


题目描述

Interleaving String

 

Given s1s2s3, 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.


题目分析

解法一:(递归)

一个简单的想法,是遍历s3的每个字符,这个字符必须等于s1和s2的某个字符。如果都不相等,则返回false
我们使用3个变量i,j,k分别记录当前s1,s2,s3的字符位置。
如果s3[k] = s1[i], i向后移动一位。如果s3[k]=s2[j],j向后移动一位。
这个题目主要难在如果s1和s2的字符出现重复的时候,就有两种情况,i,j都可以向后一位。
下面的算法在这种情况使用了递归,很简单的做法。但是效率非常差,是指数复杂度的。

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        if(s3.size() != (s1.size() + s2.size()))	return false;
        return isInterleaveCore(s1,0,s2,0,s3,0);
    }
    bool isInterleaveCore(const string &s1,int index1,const string &s2,int index2, const string &s3,int index3)
    {
    	if(index3 == s3.size())	return true;
    	
    	//printf("%d-%d-%d\n");
    	if(s1[index1] == s3[index3] && isInterleaveCore(s1,index1+1,s2,index2,s3,index3+1))	return true;
    	if(s2[index2] == s3[index3] && isInterleaveCore(s1,index1,s2,index2+1,s3,index3+1))	return true;
    	return false;
	}
};

解法二:(动态规划)
为了减少重复计算,就要使用动态规划来记录中间结果。

这里我使用了一个二维数组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)
class Solution {
private:
    bool f[1000][1000];
public:
    bool isInterleave(string s1, string s2, string s3) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function 
        if (s1.size() + s2.size() != s3.size())
            return false;
            
        f[0][0] = true;
        for(int i = 1; i <= s1.size(); i++)
            f[i][0] = f[i-1][0] && (s3[i-1] == s1[i-1]);
            
        for(int j = 1; j <= s2.size(); j++)
            f[0][j] = f[0][j-1] && (s3[j-1] == s2[j-1]);
            
        for(int i = 1; i <= s1.size(); i++)
            for(int j = 1; j <= s2.size(); j++)
                f[i][j] = (f[i][j-1] && s2[j-1] == s3[i+j-1]) || (f[i-1][j] && s1[i-1] == s3[i+j-1]);
                
        return f[s1.size()][s2.size()];
    }
};



总结


代码示例




推荐学习C++的资料

C++标准函数库
在线C++API查询
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值