现在的位置: 首页 > 综合 > 正文

Interleaving String

2018年04月12日 ⁄ 综合 ⁄ 共 1915字 ⁄ 字号 评论关闭

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.

第一反应肯定要用DP的,用递归逻辑虽然简单,但肯定要超时的,但想着反正锻炼嘛,就先写了递归的。

吸取昨天微软面试的教训,发现纸上写代码还是不够简洁,尤其是不够细心,老是写到后边发现前边忘了什么东西,果不其然刚才纸上写递归的时候递归出口就忘写了,晕。

1.递归解法:

基本思路是用三个指针分别P1,P2,P3分别指向S1,S2,S3中的位置,P1往后P2往后是需要简直是否与P3往后匹配的,现在如果S3[P3]与S1,S2当前位置都不等,肯定是返回false,如果与s1当前位置匹配,那就尝试用p1+1往后递归匹配,如果与s2当前位置匹配,那就尝试用p2+1后的位置匹配,注意这两种情况成立一个就可以了;如果p1,p2其中一个先到底了,那就单独匹配另一个好了

代码如下:

bool isInterleave(string s1,string s2,string s3)
{
	int n1=s1.length(),n2=s2.length(),n3=s3.length();
	if ( n1+n2!=n3 )
		return false;
	return _check(s1,0,s2,0,s3,0);
}

bool _check(const string& s1,int p1,const string& s2,int p2,const string& s3,int p3)
{
	if ( p1==s1.size() )
		return _compare(s2,p2,s3,p3);
	else if (p2==s2.size())
		return _compare(S1,P1,S3,P3);

	bool ans=false;

	if (s3[p3]==s1[p1])
		ans=_check(s1,p1+1,s2,p2,s3,p3+1);
	if (ans)
		return ans;

	if (s3[p3]==s2[p2])
		ans=_check(s1,p1,s2,p2+1,s3,p3+1);
}

bool _compare(const string& s1,int p1,const string& s2,int p2)
{
	while(p1!=s1.size()&&p2!=s2.size())
	{
		if (s1[p1]!=s2[p2])
			return false;
		p1++;
		p2++;
	}
	if ( p1!=s1.size()||p2!=s2.size())
		return false;
	return true;
}

2.DP版本解法

首先我们定义  f (i ,j )表示 s1的前i个字符和s2的前j个字符是否能组成s3的前(i+j)个字符,结果是1表示能组成,0表示不可以。

现在我们考虑把s1中第i+1个字符放进来,很明显 f (i+1,j) = 1的条件是 f(i,j) && s1[i+1] == s3[i+j+1],对吧~

所以我们可以得到状态转移方程是(这里i,j表示的是第i,j个字符,不是下标哈,所以换做下标的时候要-1):

 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] ) ) ? 1 : 0;

注意为了防止越界的问题我们多加了外边一圈,用来表示某一个字符串是空的时候的情况:

代码如下:

bool isInterleave(string s1,string s2,string s3)
{
	int n1=s1.length(),n2=s2.length(),n3=s3.length();
	if ( n1+n2!=n3 )
		return false;


	vector<vector<int> > dp(n1+1,vector<int>(n2+1,0) );
	dp[0][0]=1;


	int i ,j;
	for(i=1;i<=n1;i++)
		dp[i][0]=dp[i-1][0]&&s1[i-1]==s3[i-1]?1:0;
	for(j=1;j<=n2;j++)
		dp[0][j]=dp[0][j-1]&&s2[j-1]==s3[j-1]?1:0;


	for(i=1;i<=n1;i++)
		for(j=1;j<=n2;j++)
		{
			if ((dp[i-1][j]&&s1[i-1]==s3[i+j-2])
					|| (dp[i][j-1]&&s2[j-1]==s3[i+j-2]))
				dp[i][j]=1;
		}
	return dp[n1][n2];
}

【上篇】
【下篇】

抱歉!评论已关闭.