leetcode 516 最长回文子序列

简介: leetcode 516 最长回文子序列

最长回文子序列

和647类似

c610afed07bc43d888cbfcaae6ec334c.png

动态规划

  • 确定dp数组(dp table)以及下标的含义
    dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]。
  • 确定递推公式
    在判断回文子串的题目中,关键逻辑就是看s[i]与s[j]是否相同。

如果s[i]与s[j]相同,

  • j - i ==0 , dp[i][j] = 1;
  • j - i == 1, dp[i][j] = 2;
  • j - i > 2, dp[i][j] = dp[i + 1][j - 1] + 2;

1042b45ce7714e2997c6c74abab8c25e.png

  • 如果s[i]与s[j]不同
    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);

fe6bacb19f8444adb9e54b633c8207fc.png

确定遍历顺序

从递推公式dp[i][j] = dp[i + 1][j - 1] + 2 和 dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]) 可以看出,dp[i][j]是依赖于dp[i + 1][j - 1] 和 dp[i + 1][j],

也就是从矩阵的角度来说,dp[i][j] 下一行的数据。 所以遍历i的时候一定要从下到上遍历,这样才能保证,下一行的数据是经过计算的。


d988b3e3658b4de8bdb785005d6ffa7b.png

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        if(s.size()<=1) return s.size();
        vector<vector<int>> dp(s.size() , vector<int>(s.size() ,0));
        int result = 0;
        for(int i=s.size()-1; i>=0 ;i-- )
            for(int j=i ;j<s.size();j++)
            {
                if(s[i]==s[j])
                {
                    if(j==i) dp[i][j] = 1;
                    else if(j-i==1) dp[i][j] = 2;
                    else dp[i][j] = dp[i+1][j-1] + 2;
                    if(dp[i][j] > result) result = dp[i][j];
                }else
                {
                    dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
                }
            }
        // for(int i=0;i<s.size();i++)
        // {
        //     for(int j=0;j<s.size();j++)
        //     cout<<dp[i][j]<<' ';
        //     cout<<endl;
        // }
        return result;
    }
};

二刷

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        vector<vector<int>> dp(s.size() , vector<int>(s.size() ,0 ));
        for(int i=s.size()-1 ; i>=0 ;i--)
        {
            for(int j=i ; j<s.size() ;j++)
            {
                if(s[i]==s[j])
                {
                    if(j-i == 0) dp[i][j] = 1;
                    else if(j-i == 1) dp[i][j] = 2;
                    else dp[i][j] = dp[i+1][j-1] +2;
                }else dp[i][j] = max(dp[i+1][j-1] , max(dp[i+1][j] , dp[i][j-1]));
            }
        }
        return dp[0][s.size()-1];
    }
};
相关文章
|
4月前
|
Python
【Leetcode刷题Python】376. 摆动序列
文章提供了解决LeetCode "摆动序列" 问题的Python实现代码,通过遍历整数数组并使用两个变量 down 和 up 来记录正差和负差摆动序列的长度,最终返回最长摆动子序列的长度。
43 0
|
4月前
|
Python
【Leetcode刷题Python】946. 验证栈序列
LeetCode题目“946. 验证栈序列”的Python解决方案,通过模拟栈的压入和弹出操作来验证给定的两个序列是否能通过合法的栈操作得到。
34 6
|
4月前
|
算法 Python
【Leetcode刷题Python】剑指 Offer 33. 二叉搜索树的后序遍历序列
本文提供了一种Python算法,用以判断给定整数数组是否为某二叉搜索树的后序遍历结果,通过识别根节点并递归验证左右子树的值是否满足二叉搜索树的性质。
26 3
|
4月前
|
Python
【Leetcode刷题Python】105. 从前序与中序遍历序列构造二叉树
LeetCode上105号问题"从前序与中序遍历序列构造二叉树"的Python实现,通过递归方法根据前序和中序遍历序列重建二叉树。
31 3
|
4月前
|
算法 Python
【Leetcode刷题Python】300. 最长递增子序列
LeetCode 300题 "最长递增子序列" 的两种Python解决方案:一种使用动态规划,另一种使用贪心算法结合二分查找。
41 1
|
4月前
|
算法 Java
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
44 0
|
4月前
|
Python
【Leetcode刷题Python】674. 最长连续递增序列
LeetCode 674题 "最长连续递增序列" 的Python解决方案,使用动态规划算法找出给定整数数组中最长连续递增子序列的长度。
105 0
|
6月前
|
存储
力扣-2904最短且字典序最小的美丽子序列
力扣-2904最短且字典序最小的美丽子序列
41 1
|
6月前
|
存储 算法
力扣经典150题第四十六题:最长连续序列
力扣经典150题第四十六题:最长连续序列
29 0
|
6月前
|
算法 索引
力扣经典150题第二十六题:判断子序列
力扣经典150题第二十六题:判断子序列
30 0