1. 程式人生 > 其它 >程式設計學習筆記(LeetCode-516. 最長迴文子序列)

程式設計學習筆記(LeetCode-516. 最長迴文子序列)

程式設計學習筆記(LeetCode-516. 最長迴文子序列)

<516>最長迴文子序列

  • 問題重述:
    設有以字串 \(s\) ,找出其最長迴文子序列,並且返回該序列的長度。


    子序列: 不改變剩餘字元順序的情況下,刪除某些字元或者不刪除任何字元形成的一個序列。
    迴文: 即是正讀和反讀都一樣的字串(例如:aba,abba,bbbb等)。


    注: 單個字元也被認為是一個迴文串;

示例1:

輸入: s = "bbbab"
輸出: 4
解釋: 一個可能的最長迴文子序列為 "bbbb" 。

示例2:

輸入: s = "cbbd"
輸出: 2
解釋: 一個可能的最長迴文子序列為 "bb" 。

限定:
\(1 \leqslant s.length \leqslant 1000\)
\(s\) 僅由小寫英文字母組成

解析與求解(動態規劃)

  • 對於一個子序列,若它是迴文子序列,且長度大於 2 ,去其首位,其仍是一個迴文子序列。
  • 若用 \(dp[i][j]\) 表示 \(s[i,j]\) 內最長的迴文子串長度,且 \(n\) 為字串的長度,那麼:
\[\begin{cases} dp[i][j]>0,\qquad 0\leqslant i\leqslant j<n;\\ dp[i][j]=0,\qquad i,j\in (-\infty , 0)\cup [n, \infty);\\ \end{cases} \]
  • 由於任何長度為1的子序列都是迴文子序列,那麼:
\[dp[i][j]=1,\qquad i=j\ and\ 0\leqslant i\leqslant j<n; \]
  • \(i<j\) 時,需要分別考慮 \(s[i]=s[j]\)\(s[i]\neq s[j]\) 的情況。
    \(s[i]=s[j]\) 時:\[dp[i][j]=dp[i+1][j-1]+2 \]\(s[i] \neq s[j]\) 時:\[dp[i][j]=max(dp[i+1][j],\ dp[i][j-1]) \]

dp計算順序:

  • 我們想要的結果最終會落在 \(dp[0][n-1]\) 處。
  • 狀態轉移方程都是從長度較短的子序列向長度較長的子序列轉移。
    那麼dp的計算順序為:
    從矩陣的右下角開始計算,每行從\((dp[i][j],\ i=j)\)
    開始計算。

C++程式碼實現:

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        //建立動態規劃陣列dp
        vector<vector<int> > dp = vector<vector<int> >(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(i > j){continue;}        //0 <= i <= j <= n
                //長度為1的字元為迴文串
                else if(i == j){dp[i][j] = 1;}
                //提示: 當是s[i]=s[j]且i和j相鄰的時候,
                //      那麼i+1=j,j-1=i,dp[i+1][j-1]即為dp[i][j]的對稱點。
                //      由於dp[i][j]的對稱點值為0,所以長度恰好是0+2
                else if(s[i] == s[j]){dp[i][j] = dp[i+1][j-1]+2;}
                //當首尾字元不相等的時候,返回去掉當前的首或者當前的尾後的最長迴文子序列
                else if(s[i] != s[j]){dp[i][j] = max(dp[i][j-1], dp[i+1][j]);}
            }
        }
        //返回最終結果
        return dp[0][s.size()-1];
    }
};

時空複雜度:

  • 時間複雜度: \(O(n^2),\ n\)為字串 \(s\) 的長度。
  • 空間複雜度: \(O(n^2),\ n\)為字串 \(s\) 的長度。



備註: 摘錄自LeetCode官方題目解析。