【动态规划】——最长回文子序列&最长重复子数组

159 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

最长回文子序列

题目

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

来源:力扣(LeetCode)

思路

1.动态规划,dp[i][j]表示从i到j位置的字符串的最长回文子序列,必然有0<=i<=j<=n-1(n为字符串的长度)

2.只有一个字符的情况能够形成长度为1的回文子序列

3.比较s.charAt(i)和s.charAt(j)位置的值是否相等相等的话在dp[i+1][j-1]的基础上+2,可以理解为向两边扩充

class Solution {
    public int longestPalindromeSubseq(String s) {
        int n = s.length();
        int[][] dp = new int[n][n];
        for(int i=n-1;i>=0;i--){
            dp[i][i]=1;
            char c1 = s.charAt(i);
            for(int j=i+1;j<n;j++){
                char c2 = s.charAt(j);
                if(c1==c2){
                    dp[i][j]=dp[i+1][j-1]+2;
                }else{
                    dp[i][j]=Math.max(dp[i+1][j],dp[i][j-1]);
                }
            }
        }
        return dp[0][n-1];
    }
}

最长重复子数组

题目

给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。

思路

1.设n = A.length, m = B.length,那么dp[i][j]表示从i到n-1的字符串和从j到m-1的字符串的最长公共前缀

代码

class Solution {
    public int findLength(int[] nums1, int[] nums2) {
       int n = nums1.length;
       int m = nums2.length;
       int[][] dp = new int[n+1][m+1];
       int res = 0;
       for(int i=n-1;i>=0;i--){
           for(int j=m-1;j>=0;j--){
               dp[i][j]=nums1[i]==nums2[j]?dp[i+1][j+1]+1:0;
               res=Math.max(res,dp[i][j]);
           }
       }
       return res;
    }
}