给出三个字符串s1, s2, s3,判断s3是否可以由s1和s2交织而成。
例如:
给定
s1 ="xxyzz",
s2 ="pyyzx",
s2 ="pyyzx",
如果s3 ="xxpyyzyzxz", 返回true
如果s3 ="xxpyyyxzzz", 返回false
"xxyzz","pyyzx","xxpyyzyzxz"
true
"xxyzz","pyyzx","xxpyyyxzzz"
false
public class Solution { public boolean isInterleave(String s1, String s2, String s3) { int len1 = s1.length(); int len2 = s2.length(); int len3 = s3.length(); if(len1+len2 !=len3){ return false; } char[] chs1 = s1.toCharArray(); char[] chs2 = s2.toCharArray(); char[] chs3 = s3.toCharArray(); //dp[i][j]代表 chs1[0...i] chs2[0...j]能否顺序匹配chs3[i+j] boolean[][] dp = new boolean[len1+1][len2+1]; //初始化 s1中取0个字符 s2中取0个字符 匹配s3从0开始的0个字符 肯定匹配true dp[0][0] = true; //s1中取0个s2中取i个 去和s3中0+i 个匹配 for(int i = 1 ; i < len2 + 1; i ++ ){ dp[0][i] = dp[0][i-1] && chs2[i-1] == chs3[i-1]; } //s2中取0个s1中取i个 去和s3中0+i 个匹配 for(int i = 1 ; i < len1 + 1; i ++ ){ dp[i][0] = dp[i-1][0] && chs1[i-1] == chs3[i-1]; } for(int i = 1 ; i < len1+1 ; i ++ ){ for(int j = 1 ; j < len2+1 ; j ++ ){ dp[i][j] = dp[i-1][j] && (chs3[i+j-1] == chs1[i-1]) || dp[i][j-1] && (chs3[i+j-1] == chs2[j-1]); } } return dp[len1][len2]; } }
s3是由s1和s2交织生成的,意味着s3由s1和s2组成,在s3中s1和s2字符的顺序是不能变化的,和子序列题型类似,这种题我们一般是用动态规划来解。
class Solution { public: bool isInterleave(string s1, string s2, string s3) { int l1 = s1.length(); int l2 = s2.length(); int l3 = s3.length(); if(l1+l2 != l3) return false; vector<vector<bool> > dp(l1+1,vector<bool>(l2+1,false)); dp[0][0] = true; for(int i=1;i<=l1;i++) dp[i][0] = dp[i-1][0] && s1[i-1]==s3[i-1]; for(int j=1;j<=l2;j++) dp[0][j] = dp[0][j-1] && s2[j-1]==s3[j-1]; for(int i=1;i<=l1;i++) for(int j=1;j<=l2;j++) dp[i][j] = (dp[i-1][j] && s1[i-1]==s3[i+j-1] || dp[i][j-1] && s2[j-1]==s3[i+j-1]); return dp[l1][l2]; } };
public class Solution { //二维动态规划 public boolean isInterleave(String s1, String s2, String s3) { if(s1 == null || s2 == null || s3 == null){ return false; } int len1 = s1.length(),len2 = s2.length(),len3 = s3.length(); if(len3 != len1+len2){ return false; } boolean[][] dp = new boolean[len1+1][len2+1]; for(int i = 0 ; i <= len1 ; i++){ for(int j = 0 ; j <=len2 ; j++){ dp[i][j] = i==0&&j==0 ? true : (i-1 >= 0 && dp[i-1][j] && s1.charAt(i-1)==s3.charAt(i+j-1)) || (j-1 >=0 && dp[i][j-1] && s2.charAt(j-1)==s3.charAt(i+j-1)); } } return dp[len1][len2]; } }
class Solution { public: // dp[i][j] 使用s1[0,1,...,i]字符串和s2[0,1,2,...,j]字符串,组合成s3(i+j) bool isInterleave(string s1, string s2, string s3) { int m=s1.length(),n=s2.length(),l=s3.length(); if(m+n != l) return false; vector<vector<bool> > dp(m+1,vector<bool>(n+1,false)); dp[0][0] = true; for(int i=1;i<=m;i++) dp[i][0] = dp[i-1][0] && s1[i-1] == s3[i-1]; for(int j=1;j<=n;j++) dp[0][j] = dp[0][j-1] && s2[j-1] == s3[j-1]; for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { dp[i][j] = (dp[i-1][j] && s1[i-1] == s3[i+j-1]) || (dp[i][j-1] && s2[j-1] == s3[i+j-1]); } } return dp[m][n]; } };
public class Solution { //dp题,求字符串S1与字符串s2交叉能否得到串S3,dp表示字符串s1的前i个字符和字符串的前j个字符能否组成字符串S3的前i+j个字符。 public boolean isInterleave(String s1, String s2, String s3) { //先考虑特殊情况 if((s1.length()+s2.length())!=s3.length()) return false; int [][]dp=new int[s1.length()+1][s2.length()+1]; //初始化 for(int i=1;i<=s2.length();i++) { dp[0][i]=(s2.charAt(i-1)==s3.charAt(i-1)?1:0); if(dp[0][i]==0)//后面不会再相等 break; } for(int j=1;j<=s1.length();j++) { dp[j][0]=(s1.charAt(j-1)==s3.charAt(j-1)?1:0); if(dp[j][0]==0) break; } dp[0][0]=1; for(int i=1;i<=s1.length();i++) { for(int j=1;j<=s2.length();j++) { if(dp[i-1][j]==1 && s3.charAt(i+j-1)==s1.charAt(i-1)) { dp[i][j]=1; } else if(dp[i][j-1]==1 && s3.charAt(i+j-1)==s2.charAt(j-1)) { dp[i][j]=1; }else { dp[i][j]=0; } } } return dp[s1.length()][s2.length()]==1?true:false; } }
/* * 目的:判断s3是否可以由s1和s2交织而成。 * 方法:动态规划 */ bool isInterleave(string s1, string s2, string s3) { int n1 = s1.size(); int n2 = s2.size(); int n3 = s3.size(); if (n1+n2!=n3) return false; vector<vector<bool>>dp(n1+1,vector<bool>(n2+1, false)); dp[0][0] = true; for (int i = 1; i<=n1;++i){ dp[i][0] = dp[i-1][0] &&(s1[i-1] == s3[i-1]); } for (int j = 1; j <=n2;++j){ dp[0][j] = dp[0][j-1] && (s2[j-1] == s3[j-1]); } for (int i = 1; i <=n1; ++i){ for (int j = 1; j<=n2; ++j){ dp[i][j] = dp[i-1][j] && (s1[i-1] == s3[i + j-1]) || dp[i][j-1] && (s2[j-1]== s3[i+j-1]); } } return dp[n1][n2]; }
public boolean isInterleave(String s1, String s2, String s3) { return dfs(s1,s2,s3,0,0,0); } public boolean dfs(String s1,String s2,String s3,int p1,int p2,int p3){ if(p1==s1.length()&&p2==s2.length()&&p3==s3.length()) return true; boolean b1 = false; boolean b2 = false; if(p1<s1.length()&&p3<s3.length()&&s3.charAt(p3)==s1.charAt(p1)) b1 = dfs(s1,s2,s3,p1+1,p2,p3+1); if(p2<s2.length()&&p3<s3.length()&&s3.charAt(p3)==s2.charAt(p2)) b2 = dfs(s1,s2,s3,p1,p2+1,p3+1); return b1||b2; }
注意:34两个dp式子是表示,s1前i个字符和s2前j个字符能否交织成s3前i+j个字符是由下面两种情况决定的:
如果以上两种情况有一种为true,那么dp[ i ] [ j ]就为true
还有一个要注意的,dp[ 0 ][ 0 ]表示空字符串和空字符串能否匹配前0个字符,答案是肯定的,所以要初始化为0。那么对应的,dp[ 0 ][ j ]和dp[ i ][ 0 ]也要对应初始化一下
public class Solution { public boolean isInterleave(String s1, String s2, String s3) { if(s1.length()+s2.length()!=s3.length()) return false; boolean[][] dp = new boolean[s1.length()+1][s2.length()+1]; dp[0][0] = true; for(int i=1;i<dp[0].length;i++) dp[0][i] = dp[0][i-1]&&s2.charAt(i-1)==s3.charAt(i-1); for(int i=1;i<dp.length;i++) dp[i][0] = dp[i-1][0]&&s1.charAt(i-1)==s3.charAt(i-1); for(int i=1;i<dp.length;i++) for(int j=1;j<dp[0].length;j++){ dp[i][j]=dp[i-1][j]&&(s1.charAt(i-1)==s3.charAt(i+j-1))||dp[i][j-1]&&(s2.charAt(j-1)==s3.charAt(i+j-1)); } return dp[s1.length()][s2.length()]; } }
public class Solution { public boolean isInterleave(String s1, String s2, String s3) { if(s1.length()+s2.length()!=s3.length()) return false; boolean[][] dp = new boolean[s1.length()+1][s2.length()+1]; dp[0][0]=true; for(int i=0,j=1;j<=s2.length();j++) dp[i][j]=(dp[i][j-1]&&s2.charAt(j-1)==s3.charAt(j-1)); for(int i=1,j=0;i<=s1.length();i++) dp[i][j]=(dp[i-1][j]&&s1.charAt(i-1)==s3.charAt(i-1)); for(int i=1;i<=s1.length();i++) { for(int j=1;j<=s2.length();j++) { dp[i][j]=(dp[i-1][j]&&s1.charAt(i-1)==s3.charAt(i+j-1))||(dp[i][j-1]&&s2.charAt(j-1)==s3.charAt(i+j-1)); } } return dp[s1.length()][s2.length()]; } }
class Solution { public: bool isInterleave(string s1, string s2, string s3) { int n = s3.size(); int s1n = s1.size(); int s2n = s2.size(); if(n <= 0 && s1n <=0 && s2n <=0 ) return true; if( n != s1n + s2n) return false; bool dp[n+1][n+1]; for(int i = 0; i < n + 1 ; i++) for(int j = 0; j < n + 1; j++) dp[i][j] = false; if(s1n > 0 && s1[0] == s3[0]) dp[1][0] = true; if(s2n > 0 && s2[0] == s3[0]) dp[0][1] = true; for(int l = 2; l <= n ; l++){ for(int i = 0; i <= l - 1; i ++){ if(dp[i][l-i-1] && s3[l-1] == s1[i]) dp[i+1][l-i-1] = true; if(dp[i][l-i-1] && s3[l-1] == s2[l-i-1]) dp[i][l-i] = true; } } return dp[s1n][s2n]; } }; // dp[i][j] 表示s1的前i长度与s2的前j长度能否组合成s3的i+j长度 //例如: // s1 = "aabcc" // s2 = "dbbca" // s3 = "aadbbcbcac" // dp[4][3]表示s1的前4长度 "aabc" 与 // s2的前3长度 "dbb" // 能否组合成s3的前5长度"aadbbc"
//典型的二维动态规划问题,动态规划好像都是一个模式我觉得,假如用i,j分别代表s1,s2字符串的取值 //下标,则可以通过dp[i][j]来判断s3字符串的前i+j(这里只是示意,不考虑下标是不是从0开始)的字符 //能不能得到,题中的意思就是通过s1,s2互相插入(有顺序的,所以能用动规),判断能不能得到s3 class Solution { public: bool isInterleave(string s1, string s2, string s3) { int len1 = s1.length(); int len2 = s2.length(); int len3 = s3.length(); if(len1+len2 != len3) return false; vector<vector<bool>> dp(len1+1,vector<bool>(len2+1,false)); dp[0][0] = true; for(int i=1;i<=len1;i++) dp[i][0] = dp[i-1][0] && (s1[i-1]==s3[i-1]); for(int j=1;j<=len2;j++) dp[0][j] = dp[0][j-1] && (s2[j-1]==s3[j-1]); for(int i=1;i<=len1;i++) { for(int j=1;j<=len2;j++) { dp[i][j] = (dp[i][j-1]&&(s2[j-1]==s3[i+j-1])) || (dp[i-1][j]&&(s1[i-1]==s3[i+j-1])); } } return dp[len1][len2]; } };
public boolean isInterleave(String s1, String s2, String s3) { if (s1.length() + s2.length() != s3.length()) return false; boolean[][] res = new boolean[s1.length() + 1][s2.length() + 1]; res[0][0] = true; for (int i = 0; i < s1.length(); i++) { res[i + 1][0] = res[i][0] && s1.charAt(i) == s3.charAt(i); } for (int i = 0; i < s2.length(); i++) { res[0][i + 1] = res[0][i] && s2.charAt(i) == s3.charAt(i); } for (int i = 0; i < s1.length(); i++) { for (int j = 0; j < s2.length(); j++) { res[i + 1][j + 1] = (res[i][j + 1] && s1.charAt(i) == s3.charAt(i + j + 1)) || (res[i + 1][j] && s2.charAt(j) == s3.charAt(i + j + 1)); } } return res[s1.length()][s2.length()]; }
public class Solution { public boolean isInterleave(String s1, String s2, String s3) { // 边界条件判定 if(s3 == null && (s1 != null || s2 != null)) return false; if((s1 == null && s2 == null) && s3 != null) return false; if(s1 == null && s2 == null && s3 == null) return true; if(s1.length() + s2.length() != s3.length()) return false; // dp[i][j]代表s1的0~i,s2的0~j,能否匹配s3的i+j boolean[][] dp = new boolean[s1.length() + 1][s2.length() + 1]; dp[0][0] = true; for(int i = 1; i < dp.length; i++){ if(dp[i-1][0] && s1.charAt(i-1) == s3.charAt(i-1)) dp[i][0] = true; } for(int j = 1; j < dp[0].length; j++){ if(dp[0][j-1] && s2.charAt(j-1) == s3.charAt(j-1)) dp[0][j] = true; } for(int i = 1; i < dp.length; i++){ for(int j = 1; j < dp[0].length; j++){ if(dp[i][j-1]){ if(s2.charAt(j-1) == s3.charAt(i+j-1)) dp[i][j] = true; } else if(dp[i-1][j]){ if(s1.charAt(i-1) == s3.charAt(i+j-1)) dp[i][j] = true; } } } return dp[s1.length()][s2.length()]; } }
public class Solution { public boolean isInterleave(String s1, String s2, String s3) { if(s1.length() + s2.length() != s3.length()) return false; boolean[][] dp = new boolean[s1.length() + 1][s2.length() + 1]; dp[0][0] = true; for (int i = 1; i < dp.length; i ++ ) { dp[i][0] = s1.charAt(i - 1) == s3.charAt(i - 1); } for (int i = 1; i < dp[0].length; i ++ ) { dp[0][i] = s2.charAt(i - 1) == s3.charAt(i - 1); } for (int i = 1; i < dp.length; i ++ ) { for (int j = 1; j < dp[0].length; j ++ ) { if(s3.charAt(i + j - 1) == s1.charAt(i - 1) && dp[i - 1][j]) dp[i][j] = true; else if(s3.charAt(i + j - 1) == s2.charAt(j - 1) && dp[i][j - 1]) dp[i][j] = true; } } return dp[s1.length()][s2.length()]; } }
class Solution { public: bool isInterleave(string s1, string s2, string s3) { if(s3.size() != s1.size() + s2.size()) return false; if(s3.empty()) return true; vector<vector<bool> > dp(s1.size()+1, vector<bool>(s2.size()+1, false)); dp[0][0] = true; for(int i = 0; i < s1.size(); i++) { if(s1[i] != s3[i]) break; dp[i+1][0] = true; } for(int i = 0; i < s2.size(); i++) { if(s2[i] != s3[i]) break; dp[0][i+1] = true; } for(int i = 1; i <= s1.size(); i++) { for(int j = 1; j <= s2.size(); j++) { if((dp[i-1][j] && s3[i+j-1] == s1[i-1]) || (dp[i][j-1] && s3[i+j-1] == s2[j-1])) { dp[i][j] = true; } } } return dp[s1.size()][s2.size()]; } };
"求是否存在",毫无疑问,又是一道动态规划题。设当前子序列为S1[0..i],S2[0..j],S3[0..i+j+1],dp[i+1][j+1]==true表示S3[0..i+j]可以由S1[0..i]和S2[0..j]交叉组成,得到如下状态推导公式:
注意:如果S1的最大下标为i,S2最大下标为j,那么合并S1和S2之后的最大下标为i+j+1
classSolution { public: /** * * @param s1 string字符串 * @param s2 string字符串 * @param s3 string字符串 * @return bool布尔型 */ bool isInterleave(string s1, string s2, string s3) { // write code here inta = s1.size(), b = s2.size(), c = s3.size(); if(a + b != c) return false; vector<vector<bool> > dp(a+1, vector<bool>(b+1, false)); dp[0][0] = true; for(inti = 0; i < a && s1[i] == s3[i]; ++i) dp[i+1][0] = true; for(inti = 0; i < b && s2[i] == s3[i]; ++i) dp[0][i+1] = true; for(inti = 0; i < a; ++i) { for(intj = 0; j < b; ++j) { intm = s1[i], n = s2[j], o = s3[i+j+1]; if(m == o && n != o) dp[i+1][j+1] = dp[i][j+1]; if(m != o && n == o) dp[i+1][j+1] = dp[i+1][j]; if(m == o && n == o) dp[i+1][j+1] = dp[i][j+1] || dp[i+1][j]; if(m != o && n != o) dp[i+1][j+1] = false; } } return dp[a][b]; } };
vector<vector<int> > visited(row,vector<int>(column,6));//初始化一个 二维vector 行row,列column ,且 值为data=6 自定义data;
class Solution { public: bool isInterleave(string s1, string s2, string s3) { int pos1,pos2,pos3; pos1=0;pos2=0;pos3=0; int len1=s1.size(); int len2=s2.size(); int len3=s3.size(); vector<int>flag(len3,0); stack<int>path1; stack<int>path2; stack<int>path3; while(pos3<len3) { if(pos1<len1&&pos2<len2&&s1[pos1]==s3[pos3]&&s2[pos2]==s3[pos3]) { path3.push(pos3); path2.push(pos2); path1.push(pos1); pos1++; pos3++; } else if(pos1<len1&&s1[pos1]==s3[pos3]) { pos1++; pos3++; } else if(pos2<len2&&s2[pos2]==s3[pos3]) { pos2++; pos3++; } else { if(path3.empty())return false; else { pos1=path1.top(); path1.pop(); pos2=path2.top(); path2.pop(); pos3=path3.top(); path3.pop(); pos2++; pos3++; } } } return pos3==len3&&pos2==len2&&pos1==len1; } };看到大家都用的动态规划,我是个憨憨硬仿真,竟然过了,换成递归估计过不了,用的循环和栈结构