516. Longest Palindromic Subsequence

516. Longest Palindromic Subsequence

這一題和 647. Palindromic Substrings 很像,只是其中的差異是一個問的是「子字串」,一個問的是「子序列」。

子序列的排列情況會比子字串多很多,可是其實比較好想,利用回文的特性,我們要檢查的狀態就只有兩種:

  1. 頭尾一樣,接著繼續檢查中間的最長回文子序列。

  2. 頭尾不同,分別看先移動頭部的指標,和先移動尾部的指標,看哪邊可以拿到比較長的回文子序列。

遞迴

這樣的情況就可以寫出遞迴的關係式,其中有兩種基本狀況要處理,繼續複習回文的特性,那就是要考慮字串的長度是奇數或是偶數。

  1. 如果是奇數長度的回文,最終的情況會是左右指針指向同一個位置,這時候的回文長度是 1

  2. 如果是偶數長度的回文,最終的情況會是左右指針相鄰,位置差一,且兩個字是一模一樣的,這時候的回文長度是 2

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:

        def helper(i, j):
            # 長度為奇數的回文
            if i == j:
                return 1
            # 長度為偶數的回文
            elif j - i == 1 and s[i] == s[j]:
                return 2
            else:
                # 頭尾一樣,接著繼續檢查中間的最長回文子序列。
                if s[i] == s[j]:
                    return 2 + helper(i+1, j-1)
                # 頭尾不同,分別看先移動頭部的指標,和先移動尾部的指標,
                # 看哪邊可以拿到比較長的回文子序列。
                else:
                    return max(helper(i+1, j), helper(i, j-1))
        return helper(0, len(s)-1)

自頂向下

上面的題目,很明顯的存在重疊的子問題,因此可以透過記憶法來減少運算的次數。

Python 內建的記憶法

自己實作記憶法

自底向上

Last updated