[LeetCode] Longest Palindromic Subsequence 最長迴文子序列

 

Given a string s, find the longest palindromic subsequence's length in s. You may assume that the maximum length of s is 1000.html

Example 1:
Input:java

"bbbab"

Output:算法

4

One possible longest palindromic subsequence is "bbbb".數組

 

Example 2:
Input:緩存

"cbbd"

Output:post

2

One possible longest palindromic subsequence is "bb".優化

 

這道題給了咱們一個字符串,讓咱們求最大的迴文子序列,子序列和子字符串不一樣,不須要連續。而關於迴文串的題以前也作了很多,處理方法上就是老老實實的兩兩比較吧。像這種有關極值的問題,最應該優先考慮的就是貪婪算法和動態規劃,這道題顯然使用DP更加合適。咱們創建一個二維的DP數組,其中dp[i][j]表示[i,j]區間內的字符串的最長迴文子序列,那麼對於遞推公式咱們分析一下,若是s[i]==s[j],那麼i和j就能夠增長2個迴文串的長度,咱們知道中間dp[i + 1][j - 1]的值,那麼其加上2就是dp[i][j]的值。若是s[i] != s[j],那麼咱們能夠去掉i或j其中的一個字符,而後比較兩種狀況下所剩的字符串誰dp值大,就賦給dp[i][j],那麼遞推公式以下:url

              /  dp[i + 1][j - 1] + 2                       if (s[i] == s[j])spa

dp[i][j] =code

              \  max(dp[i + 1][j], dp[i][j - 1])        if (s[i] != s[j])

 

解法一:

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

 

咱們能夠對空間進行優化,只用一個一維的dp數組,參見代碼以下:

 

解法二:

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.size(), res = 0;
        vector<int> dp(n, 1);
        for (int i = n - 1; i >= 0; --i) {
            int len = 0;
            for (int j = i + 1; j < n; ++j) {
                int t = dp[j];
                if (s[i] == s[j]) {
                    dp[j] = len + 2;
                } 
                len = max(len, t);
            }
        }
        for (int num : dp) res = max(res, num);
        return res;
    }
};

 

下面是遞歸形式的解法,memo數組這裏起到了一個緩存已經計算過了的結果,這樣能提升運算效率,使其不會TLE,參見代碼以下:

 

解法三:

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.size();
        vector<vector<int>> memo(n, vector<int>(n, -1));
        return helper(s, 0, n - 1, memo);
    }
    int helper(string& s, int i, int j, vector<vector<int>>& memo) {
        if (memo[i][j] != -1) return memo[i][j];
        if (i > j) return 0;
        if (i == j) return 1;
        if (s[i] == s[j]) {
            memo[i][j] = helper(s, i + 1, j - 1, memo) + 2;
        } else {
            memo[i][j] = max(helper(s, i + 1, j, memo), helper(s, i, j - 1, memo));
        }
        return memo[i][j];
    }
};

 

相似題目:

Palindromic Substrings

Longest Palindromic Substring

 

參考資料:

https://discuss.leetcode.com/topic/78603/straight-forward-java-dp-solution

https://discuss.leetcode.com/topic/78799/c-beats-100-dp-solution-o-n-2-time-o-n-space

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索