目录
每日一句
给予和就受都是一份馈赠,既需要谦逊,也需要勇气
作者简介
🏡个人主页:XiaoChen_Android
📚学习专栏:力扣专栏
🕒发布日期:2022/8/18
『LeetCode|每日一题』 最长公共子序列
1.每日一题
2.解题思路
2.1 思路分析
此题是二维动态规划中的一道经典例题,定义一个二维数组dp[i][j],用来存两个字符串text1(0,i)和text2(0,j)中的最长公共子序列
S1:dp数组的长度可以扩大一位,左边界和上边界的值都为0;(当i = 0时,该字符串为空,所以值为0,这一步就是处理了动态规划的边界情况,读者可以仔细想想为何这么处理)
S2:当i > 0 ,j > 0时,开始填充dp数组,分为两种情况:(由于考虑的dp[i][j]的值,它减少一位字符则由字符串的前一位决定)
- 当text1.charAt(i - 1) == text2.charAt(j - 1)时,再增加一位字符就得到了dp[i][j],dp[i][j] = dp[i - 1][j - 1] + 1;
- 当text1.charAt(i - 1) != text2.charAt(j - 1)时,考虑两种情况:
- text1范围在(0,i)和text2范围在(0.j -1)的最长公共子序列
- text1范围在(0,i - 1)和text2范围在(0.j)的最长公共子序列
- 要使得dp[i][j]最大,则应该取dp[i][j - 1]和dp[i - 1][j]中的最大值
S3:最终计算得到的dp[text1.length()][text2.length()]就是最长公共子序列的长度
2.2 核心代码(dp)
for(int i = 1 ; i <= l1 ; i ++){
for(int j = 1 ; j <= l2 ; j ++){
if(t1[i - 1] == t2[j - 1]){
dp[i][j] = dp[i - 1][j - 1] + 1;
}else {
dp[i][j] = Math.max(dp[i - 1][j] , dp[i][j - 1]);
}
}
}
2.3 全部代码
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int l1 = text1.length();
int l2 = text2.length();
char[] t1 = new char[l1];
char[] t2 = new char[l2];
int[][] dp = new int[l1 + 1][l2 + 1];
for(int i = 0 ; i < l1 ; i ++){
t1[i] = text1.charAt(i);
}
for(int i = 0 ; i < l2 ; i ++){
t2[i] = text2.charAt(i);
}
for(int i = 1 ; i <= l1 ; i ++){
for(int j = 1 ; j <= l2 ; j ++){
if(t1[i - 1] == t2[j - 1]){
dp[i][j] = dp[i - 1][j - 1] + 1;
}else {
dp[i][j] = Math.max(dp[i - 1][j] , dp[i][j - 1]);
}
}
}
return dp[l1][l2];
}
}
2.4 运行结果
3.第二种解法(递归)----此题中会超时
3.1 全部代码
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int l1 = text1.length();
int l2 = text2.length();
char[] t1 = new char[l1];
char[] t2 = new char[l2];
for(int i = 0 ; i < l1 ; i ++){
t1[i] = text1.charAt(i);
}
for(int i = 0 ; i < l2 ; i ++){
t2[i] = text2.charAt(i);
}
int ans = dp(t1 , t2 , l1 , l2);
return ans;
}
private static int dp(char[] t1 , char[] t2 , int l1 , int l2){
int[][] cc = new int[l1 + 1][l2 + 1];
if(l1 == 0 || l2 == 0){
return 0;
}else if(t1[l1 - 1] == t2[l2 - 1]){
cc[l1][l2] = dp(t1 , t2 , l1 - 1 , l2 - 1) + 1;
}else {
cc[l1][l2] = Math.max(dp(t1 , t2 , l1 - 1 , l2) , dp(t1 , t2 , l1 , l2 - 1));
}
return cc[l1][l2];
}
}
3.2 解析
思路同dp解法类似,不过这个方法的边界处理是用长度来取代的,即l1 == 0 || l2 == 0
众所周知,递归虽然容易理解,但是递归的过程是非常耗时的,在对时间复杂度没有要求的情况下可以用递归求解,否则用动态规划是最为合理的
3.3 运行结果
🍁 类似题目推荐:
如果文章对你有帮助就支持一下噢,新手尝试,不好的地方请各位大佬多多指教!