题意:

  • 给定一个字符串,找到其中最长的回文子序列,并返回该序列的长度。

方法一:动态规划

解题思路:

  • 求解最长回文子序列,有明显的子问题重叠,使用动态规划,考虑以下最优子结构:
    (1)dp[i][j]-----序列s[i]-->s[j]的最长回文子序列的长度。
    (2)dp[i][i]=1
    (3)dp[i][j]=0(j<i)
    (4)dp[i][j]=dp[i+1][j-1]+2 (if s[i]==s[j])
    (5)dp[i][j]=max(dp[i+1,j],dp[i,j-1]) (if s[i]!=s[j])
  • (2)显然,(3)是对(4)的边界条件的兼容,(4)易得,(5)由于s[i]!=s[j],那么s[i]和s[j]最多只有一个能加入到最长回文子序列中,因此从两者中取最大值。

图解如下:

图片说明

代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param s string 一个字符串由小写字母构成,长度小于5000
     * @return int
     */
    int longestPalindromeSubSeq(string s) {
        // write code here
        int n=s.size();
        vector<vector<int>> dp(n,vector<int>(n));
        //i为起始索引,j为结束索引
        for(int i=n-1;i>=0;i--){
            dp[i][i]=1;
            for(int j=i+1;j<n;j++){
                //相同,则加2
                if(s[i]==s[j])
                    dp[i][j]=dp[i+1][j-1]+2;
                //不同,则从dp[i+1][j] dp[i][j-1]中寻找最大值。
                else
                    dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
            }
        }
        return dp[0][n-1];
    }
};

复杂度分析:

时间复杂度:,对数组dp的遍历更新,遍历次数为n^2/2,故
空间复杂度:,二维数组dp。

方法二:

解题思路:

  • 方法一中的二维数组dp,我们通过图解和代码发现,每一个只依赖于,,。因此,我们只需要一维数组即可。
  • 同时由于依赖于,因此i需要从大往小遍历。

代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param s string 一个字符串由小写字母构成,长度小于5000
     * @return int
     */
    int longestPalindromeSubSeq(string s) {
        // write code here
        int n=s.size();
        vector<int> dp(n,1);
        //i为起始索引,j为结束索引
        for(int i=n-1;i>=0;i--){
            int pre=0;
            for(int j=i+1;j<n;j++){
                //临时变量存储dp[j],需要更新为下一轮遍历的pre
                int tmp=dp[j];
                //相同,则加2
                if(s[i]==s[j])
                    dp[j]=pre+2;
                //不同,则从dp[j] dp[j-1]中寻找最大值。更新到dp[j]
                else
                    dp[j]=max(dp[j],dp[j-1]);
                pre=tmp;
            }
        }
        return dp[n-1];
    }
};

复杂度分析:

时间复杂度:,同上。
空间复杂度:,一位数组dp,维度为n。