给出三个字符串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;
}
}; 看到大家都用的动态规划,我是个憨憨硬仿真,竟然过了,换成递归估计过不了,用的循环和栈结构