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.
输入数组s1,s2和s3,判断s3是否是由s1和s2中的元素交替组成的。面试
乍一看这题能够经过递归的方式来求解。咱们能够同时判断当前下标s1和s2的元素是否是和s3当前下标的元素相同。若是相同,就进入下一轮递归。
代码以下:数组
public boolean isInterleave(String s1, String s2, String s3) { if(s1.length() + s2.length() != s3.length()) return false; return isInterleave(s1, s2, s3, 0,0,0); } public boolean isInterleave(String s1, String s2, String s3, int pointer1, int pointer2, int pointer3){ if(pointer1==s1.length() && pointer2==s2.length())return pointer3 == s3.length(); if(pointer1<s1.length() && s1.charAt(pointer1)==s3.charAt(pointer3) && isInterleave(s1,s2,s3,pointer1+1, pointer2, pointer3+1)) return true; if(pointer2<s2.length() && s2.charAt(pointer2)==s3.charAt(pointer3) && isInterleave(s1,s2,s3,pointer1, pointer2+1, pointer3+1)) return true; return false; }
这段代码 不出意外的 超时了
微信
由于这里有太多的重复调用了。不少的判断在第一次递归的过程当中就能够知道,数组在走到s1和s2中的某个位置pointer1,pointer2时会进入死胡同。而走到pointer1和pointer2对应的s3中的pointer3也是肯定的。因此若是咱们能够利用这部分信息,就能够省略掉不少重复的判断。这里咱们利用boolean[][]
数组记录判断状况。数据结构
public boolean isInterleave2(String s1, String s2, String s3) { if(s1.length() + s2.length() != s3.length()) return false; return isInterleave(s1, s2, s3, 0,0,0, new boolean[s1.length()+1][s2.length()+1]); } public boolean isInterleave(String s1, String s2, String s3, int pointer1, int pointer2, int pointer3, boolean[][] isInvalid){ if(isInvalid[pointer1][pointer2]) return false; if(pointer3 == s3.length())return true; boolean isValid = pointer1<s1.length() && s1.charAt(pointer1)==s3.charAt(pointer3) && isInterleave(s1,s2,s3,pointer1+1,pointer2, pointer3+1, isInvalid) || pointer2<s2.length() && s2.charAt(pointer2)==s3.charAt(pointer3) && isInterleave(s1,s2,s3,pointer1,pointer2+1,pointer3+1,isInvalid); if(!isValid) isInvalid[pointer1][pointer2]=true; return isValid; }
一样适用boolean[][]
做为存储临时值的数据结构,这里咱们将其表明的含义改变为至下标(i,j)时是否能够和前(i-1,j)或是(i,j-1)上的值链接知足s3。
解释以下:在这里(i,j)
位置值的含义表明若是采用s2的前i个值和s1的前j个值,是否能够组成s3前i+j个值。因此判断(i,j)须要参考(i-1,j)和(i,j-1)位置上的值。若是(i-1,j)成立,也就是说s2的前i-1个值和s1的前j个值能够组成s3前i+j-1个值,那么若是s2的第i个值等于s3的第i+j个值,那么该式子成立。(i,j-1)也是同理的。spa
public boolean isInterleave3(String s1, String s2, String s3){ if ((s1.length()+s2.length())!=s3.length()) return false; boolean[][] matrix = new boolean[s2.length()+1][s1.length()+1]; matrix[0][0] = true; for(int i = 1 ; i<s1.length()+1 ; i++){ matrix[0][i] = matrix[0][i-1] && s1.charAt(i-1)==s3.charAt(i-1); } for(int i = 1 ; i<s2.length()+1 ; i++){ matrix[i][0] = matrix[i-1][0] && s2.charAt(i-1)==s3.charAt(i-1); } for(int i = 1 ; i<matrix.length ; i++){ for(int j = 1 ; j<matrix[0].length ; j++){ matrix[i][j] = (matrix[i-1][j] && s2.charAt(i-1)==s3.charAt(i+j-1)) ||(matrix[i][j-1] && s1.charAt(j-1)==s3.charAt(i+j-1)); } } return matrix[s2.length()][s1.length()]; }
在上一种思路中,咱们能够看到,其实在每一层的遍历中只有上一层数据和前一个数据对当前数据有参考价值。因此咱们能够将boolean[][]的二维数组简化为boolean[]一维数组的数据结构
。提升空间的利用率。code
public boolean isInterleave4(String s1, String s2, String s3){ if ((s1.length()+s2.length())!=s3.length()) return false; boolean[] matrix = new boolean[s2.length()+1]; for(int i = 0 ; i<=s1.length() ; i++){ for(int j = 0 ; j<=s2.length() ; j++){ if(i==0&&j==0){ matrix[j] = true; }else if(i==0){ matrix[j] = matrix[j-1] && s2.charAt(j-1)==s3.charAt(j-1); }else if(j==0){ matrix[j] = matrix[j] && s1.charAt(i-1) == s3.charAt(i-1); }else{ matrix[j] = (matrix[j-1] && s2.charAt(j-1)==s3.charAt(i+j-1)) || (matrix[j] && s1.charAt(i-1)==s3.charAt(i+j-1)); } } } return matrix[s2.length()]; }
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注个人微信公众号!将会不按期的发放福利哦~orm