Day37 | 647回文子串&516最长回文子序列

47 阅读1分钟

回文子串 LeetCode 647

题目链接:[LeetCode 647 - 中等]

思路

使用动态规划,并且从后向前遍历。

情况1:单个字符->为回文子串、 情况2:两个字符 代码:if(chars[i]==chars[j]){if(j-i<=1){res++;dp[i][j]=true;}

情况3:内部为回文子串且坐标为i和j的部分相等 代码:if(chars[i]==chars[j]){else if(dp[i+1][j-1]){res++;dp[i][j]=true; }}

动态规划:

class Solution {
    public int countSubstrings(String s) {
        char[] chars = s.toCharArray();
        int len = chars.length;
        int res=0;
        boolean[][] dp = new boolean[len][len];
        for(int i=len-1;i>=0;i--){
            for(int j=i;j<len;j++){
                if(chars[i]==chars[j]){
                    if(j-i<=1){
                        res++;
                        dp[i][j]=true;
                    }else if(dp[i+1][j-1]){
                        res++;
                        dp[i][j]=true;
                    }
                }
            }
        }
        return res;
    }
}

最长回文子序列 LeetCode 516

题目链接:[LeetCode 516 - 中等]

思路

动规五部曲:

①dp数组的含义: dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]

②递推公式: dp[i][j]=dp[i+1][j-1]+2

③初始化: dp[i][i]=1; 当i与j相同,那么dp[i][j]一定是等于1的

④遍历顺序: for (int i = s.size() - 1; i >= 0; i--) { for (int j = i + 1; j < s.size(); j++)

dp[i][j] 依赖于 dp[i + 1][j - 1] ,dp[i + 1][j] 和 dp[i][j - 1]

⑤举例推导dp数组(略)

动态规划:

class Solution {
    public int longestPalindromeSubseq(String s) {
        int[][] dp = new int[s.length()+1][s.length()+1];

        for(int i=s.length()-1;i>=0;i--){
            dp[i][i]=1;
            for(int j=i+1;j<s.length();j++){
                if(s.charAt(i)==s.charAt(j)){
                    dp[i][j]=dp[i+1][j-1]+2;
                }else{
                    dp[i][j]=Math.max(Math.max(dp[i+1][j],dp[i][j-1]),dp[i][j]);
                }
            }
        }

        return dp[0][s.length()-1];
    }
}