剑指offer 专项突破版 95、最长公共子序列

题目链接

思路
  • 这道题前面都是做的单序列的题目,也就是说输入的内容是一个数组或者是字符串。现在以及后面的几道题都是双序列,也就是说要处理的数据有两个数组或者字符串,对于双序列的题目,一般的状态转移方程有两个参数,因此我们需要找到f(i,j)和f(i-1,j-1)、f(i-1,j)、f(i,j-1)的关系
  • 假设f(i,j)是s1的前i个字符和s2的前j个字符可以形成的最大公共序列,那么最终的结果即为求f(s1.length(),s2.length())
  • 首先找递推关系(这里书上讲的很清楚)
    • 如果chi = chj 那么有 f(i,j)=f(i-1,j-1)+1
    • 如果chi != chj 那么有 f(i,j)=max{f(i-1,j),f(i,j-1)} (因为此时chi和chj一定不能同时出现在共同子序列中)
  • 解决了递归式后还需要处理边界值,可以发现f(i,0)和f(i-1,-1)有关、f(0,j)和f(-1,j-1)有关,也就是说我们在从小到大填充数组内容时还需要先计算-1的值,具体到答案数组中我们可以额外增添一列,这样可以简化我们代码的书写
  • 首先有f(-1,-1)是0,这里要联系f(i,j)的意义,即s1的前i个字符和s2的前j个字符可以形成的最大公共序列,那么前-1个字符形成的最大公共子序列自然是0,同理f(-1,j)和f(i,-1)自然也全都是0
  • 最后一点 这个题可以进行状态压缩,因为f(i,j)在计算时之和他左边相邻、上面相邻、左上相邻的三个数有关,所以可以只用2行来保存即可
class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
		
    	int[][] dp = new int[2][text2.length()+1];
 
        for(int i = 0 ;i < text1.length();i++){
            for(int j = 0 ;j < text2.length();j++){
            	if(text1.charAt(i) == text2.charAt(j))
                	dp[(i+1)%2][j+1] = dp[(i)%2][j] + 1;
                else
                	dp[(i+1)%2][j+1] = Math.max(dp[(i)%2][j+1],dp[(i+1)%2][j]);
            }
        }

        return dp[text1.length()%2][text2.length()];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值