leetcode 97. Interleaving String(字串交錯出現) DFS深度優先遍歷 + 很明顯很經典的DP動態規劃做法
阿新 • • 發佈:2018-12-24
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.
When you see string problem that is about subsequence or matching, dynamic programming method should come to your mind naturally.
題意很簡答,就是問一下字串可以不可以通過兩個字串交替出現得到。最自覺的方法就是DFS深度優先遍歷,但是這個可能會超時(我驗證過了,的確會超時)。
一般遇到字串匹配的問題都應當想到DP動態規劃。
參考程式碼吧,這道題很經典,很值得學習。
程式碼如下:
/*
* When you see string problem that is about subsequence or matching,
* dynamic programming method should come to your mind naturally.
* */
public class Solution
{
public boolean isInterleave(String s1, String s2, String s3)
{
if (s1==null || s2==null || s3==null || s1.length()+s2.length()!=s3.length())
return false;
//遞迴超時
//return Recursive1(s1, s2, s3, 0, 0, 0);
return byDP(s1,s2,s3);
}
/*
* When you see string problem that is about subsequence or matching,
* dynamic programming method should come to your mind naturally.
*
* 所以這道題還是用DP的思想解決。大體思路是,s1取一部分s2取一部分,
* 最後是否能匹配s3。動態規劃陣列是dp[i][j],表示:s1取前i位,s2取前j位,
* 是否能組成s3的前i+j位。初始化是,假設s1為空,那麼s2每一位跟s3匹配放入dp[0][j];
* 假設s2為空,那麼s1每一位跟s3匹配放入dp[i][0]。
* */
boolean byDP(String s1, String s2, String s3)
{
boolean [][]dp=new boolean[s1.length()+1][s2.length()+1];
dp[0][0]=true;
for(int i=1;i<s1.length()+1;i++)
{
if(s1.charAt(i-1)==s3.charAt(i-1) && dp[i-1][0])
dp[i][0]=true;
}
for(int i=1;i<s2.length()+1;i++)
{
if(s2.charAt(i-1)==s3.charAt(i-1) && dp[0][i-1])
dp[0][i]=true;
}
//遍歷 DP
for(int i=1;i<s1.length()+1;i++)
{
for(int j=1;j<s2.length()+1;j++)
{
if(s3.charAt(i+j-1)==s1.charAt(i-1) && dp[i-1][j])
dp[i][j]=true;
if(s3.charAt(i+j-1)==s2.charAt(j-1) && dp[i][j-1])
dp[i][j]=true;
}
}
return dp[s1.length()][s2.length()];
}
//這是遞迴解法
boolean Recursive(String s1, String s2, String s3, int i, int j,int k)
{
if(i==s1.length() && j==s2.length() && k==s3.length())
return true;
else if( i<s1.length() && s3.charAt(k)==s1.charAt(i)
&& j<s2.length() && s3.charAt(k)==s2.charAt(j) )
{
if(Recursive(s1, s2, s3, i+1, j, k+1))
return true;
else
return Recursive(s1, s2, s3, i, j+1, k+1);
}
else if(i<s1.length() && s3.charAt(k)==s1.charAt(i))
return Recursive(s1, s2, s3, i+1, j, k+1);
else if(j<s2.length() && s3.charAt(k)==s2.charAt(j))
return Recursive(s1, s2, s3, i, j+1, k+1);
else
return false;
}
}
下面是C++的做做法,
當你遇到字串匹配的時候最直覺的方法就是DP動態規劃。
程式碼如下:
#include<iostream>
#include <vector>
using namespace std;
//當你遇到字串匹配的時候一般都要想到DP動態規劃的做法
class Solution
{
public:
bool isInterleave(string s1, string s2, string s3)
{
if (s3.length() != s1.length() + s2.length())
return false;
vector<vector<bool>> dp(s1.length()+1,vector<bool>(s2.length()+1,0));
dp[0][0] = true;
for (int i = 1; i <= s1.length(); i++)
{
if (s1[i-1] == s3[i-1] && dp[i - 1][0])
dp[i][0] = true;
}
for (int i = 1; i <= s2.length(); i++)
{
if (s2[i-1] == s3[i-1] && dp[0][i-1])
dp[0][i] = true;
}
for (int i = 1; i <= s1.length(); i++)
{
for (int j = 1; j <= s2.length(); j++)
{
if (s3[i + j - 1] == s1[i - 1] && dp[i - 1][j])
dp[i][j] = true;
if (s3[i + j - 1] == s2[j - 1] && dp[i][j-1])
dp[i][j] = true;
}
}
return dp[s1.length()][s2.length()];
}
};