做这道题花了点时间,记录下。
注:子序列可以不连续。子串一定是连续的。
题目
给定两个字符串 text1
和 text2
,返回这两个字符串的最长公共子序列的长度。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,”ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。
若这两个字符串没有公共子序列,则返回 0。
示例 1:
1 2 3
| 输入:text1 = "abcde", text2 = "ace" 输出:3 解释:最长公共子序列是 "ace",它的长度为 3。
|
示例 2:
1 2 3
| 输入:text1 = "abc", text2 = "abc" 输出:3 解释:最长公共子序列是 "abc",它的长度为 3。
|
示例 3:
1 2 3
| 输入:text1 = "abc", text2 = "def" 输出:0 解释:两个字符串没有公共子序列,返回 0。
|
题解
Round 1(失败)
思路:
既然获取公共子序列,那以短的句子为基础,遍历每个字符,判断在长句子中是否存在,如果存在则保存当前字符。最终得到公共子序列中。任意一个字符串结束都算结束。
乍一看这个思路没问题,实际不然。缺陷在下方也有说明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
class Solution { public int longestCommonSubsequence(String text1, String text2) { if(text1 == null || text2 == null || text1.isEmpty() || text2.isEmpty()) return 0;
String longString = null; char[] array = null; int res = 0; int tempResInt =0;
if(text1.length()<text2.length()) { array = text1.toCharArray(); longString = text2; }else { array = text2.toCharArray(); longString = text1; }
for(int i = 0; i<array.length; i++){ tempResInt = 0; StringBuilder tempResString = new StringBuilder() ; String tempString = longString; for(int j = i; j<array.length; j++ ) { char cur = array[j]; if (tempString.indexOf(cur) != -1) { tempResInt++; tempResString.append(cur); tempString = tempString.substring(tempString.indexOf(cur)+1); } } System.out.println("tempResInt: "+ tempResInt + ", tempResString: "+tempResString.toString()); res = Math.max(tempResInt, res); } System.out.println("length: "+ res + ", tempResInt: "); return res; }
}
|
Round 2(递归)
思路:
动态规划的思路解题。推荐看下labuladong的算法小抄。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
class Solution { public int longestCommonSubsequence(String text1, String text2) { if(text1 == null || text2 == null || text1.isEmpty() || text2.isEmpty()) return 0;
char[] arr1 = text1.toCharArray(); char[] arr2 = text2.toCharArray();
return recursion(arr1, arr2, arr1.length-1, arr2.length-1);
}
public int recursion(char[] text1, char[] text2, int i, int j){ if (i < 0 || j < 0) { return 0; }
if (text1[i] == text2[j]) { return recursion(text1, text2, i-1, j-1)+1; } else { return Math.max(recursion(text1, text2, i-1, j), recursion(text1, text2, i, j-1)); } } }
|
Round 3(数组存储结果)
思路:
与递归法类似,区别在于,将每种情况的结果存放到数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
class Solution { public int longestCommonSubsequence(String text1, String text2) { if(text1 == null || text2 == null || text1.isEmpty() || text2.isEmpty()) return 0;
char[] arr1 = text1.toCharArray(); char[] arr2 = text2.toCharArray(); int length1 = text1.length(); int length2 = text2.length(); int[][] dp = new int[length1+1][length2+1];
for (int i = 1; i < length1+1; i++) { for (int j = 1; j < length2+1; j++) { if (arr1[i-1] == arr2[j-1]) { dp[i][j] = dp[i-1][j-1]+1; } else { dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]); } } } return dp[length1][length2];
}
}
|