【ATT】Interleaving String
Q:
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.
A: DP题。这道题hulu面试出过,当时sb了,想着用递归做,但是考虑一种极限情况 XXX ,XXX,XXXXXX. 如果递归的话,分支每次要走两个支路,复杂度是O(2^n).
实际上应该用DP做。二维DP。用dp[i][j]表示s3[1~i+j]是否由s1[1~i]和s2[1~j]交织而成的。
如果s1[i] == s3[i+j]&&s2[j]!=s3[i+j],那么dp[i][j] = dp[i-1][j];
如果s1[i] != s3[i+j]&&s2[j]==s3[i+j],那么dp[i][j] = dp[i][j-1];
如果s1[i] == s3[i+j]&&s2[j]==s3[i+j],那么dp[i][j] = dp[i-1][j]||dp[i][j-1];
否则,dp[i][j] = false;
注意,边界条件的处理,当i=0||j==0的时候。
bool isInterleave(string s1, string s2, string s3) { // Start typing your C/C++ solution below // DO NOT write int main() function int m = s1.size(); int n = s2.size(); int l = s3.size(); if(m+n!=l) return false; vector<vector<bool>> dp(m+1,vector<bool>(n+1,false)); int i,j; dp[0][0] = true; for(j=1;j<=n;j++) { if(s3[j-1] == s2[j-1]) dp[0][j] = dp[0][j-1]; } for(i=1;i<=m;i++) { if(s1[i-1] == s3[i-1]) dp[i][0] =dp[i-1][0]; } for(i=1;i<=m;i++) { for(j=1;j<=n;j++) { if(s1[i-1]==s3[i+j-1]&&s2[j-1]!=s3[i+j-1]) dp[i][j] = dp[i-1][j]; else if(s2[j-1]==s3[i+j-1]&&s1[i-1]!=s3[i+j-1]) dp[i][j] = dp[i][j-1]; else if(s1[i-1]==s3[i+j-1]&&s2[j-1]==s3[i+j-1]) dp[i][j] = dp[i-1][j]||dp[i][j-1]; } } return dp[m][n]; }