5. Longest Palindromic Substring
題目網址:https://leetcode.cn/problems/longest-palindromic-substring/
題意:給一 string
s
, 找出s
中最長的迴文 substring。注意:
- substring 指的是 string 中 連續的 subset
- subsequence 則是 string 的 subset
Solution 1:
想法:利用 DP, 因為我們發現「一個迴文去掉兩頭後, 剩下的部分仍為迴文」, 我們用
dp[i][j]
代表substring s[i~j]
是否迴文, 則可得到下列公式:
dp[i][j] = (s[i] == s[j]) && dp[i + 1][j - 1]
dp[i + 1][j - 1]
在dp[i][j]
的左下方, 故順序為由左至右, 一行一行的填, 其中對角線為true
e.g.
"abba"
中已知"bb"
為迴文, 所以dp[1][2] = true
➔ 則
dp[0][3]
則因為"a" == "a"
且dp[1][2] = true
, 故dp[0][3] = true
, 代表"abba"
為迴文
class Solution { |
- time:$O(n^2)$ ➔ for loop:$1+2+…+(n-1) = \dfrac{n(n-1)}{2}$ $= O(n^2)$
- space:$O(n^2)$ ➔
dp
Solution 2:
想法:利用中心擴散法, 也就是枚舉所有 substring 的中心位置, 總共枚舉 2n 個 substring, 因為每個位置
i
皆要考慮以其為中心的偶數 substring 和奇數 substring更新
start
時, 之所以為start = i - (maxLen - 1) / 2
, 是因為我們的i
是左中點, 而非右中點, 故maxLen
要先減一再除 2
expand(s, left, right, n)
跳出迴圈時, 有兩種可能:
s[left] != s[right]
:代表s
中的[left + 1, right - 1]
區間是回文 substring, 此時的回文substring 長度為(right - 1) - (left + 1) - 1 = right - left - 1
第二種狀況是
left
或right
越界, e.g.left = -1
且right = n
, 此時代表整個s
為回文, 故回文長度為n
➔ 第一種狀況得到的公式right - left - 1 = n - (-1) - 1 = n
仍然滿足第二種狀況
class Solution { |
- time:$O(n^2)$ ➔ 遍歷每個 char, 每個 char 為中心最多往外擴散 $\dfrac{n}{2}$ 次, 得 $2 \cdot O(\dfrac{n}{2}) \cdot n$
- space:$O(1)$ ➔ 只需常數空間
Solution 3:(不會也沒差, 會前兩種方法就足夠了)
想法:利用 Manacher 演算法(可參考這篇), 其核心思想是結合 DP(回文特性)+ 中心擴散
class Solution { |
- time:$O(n)$ ➔ 透過不斷拓展
right
, 且right
只增不減, 故只看 for loop, 因為 while loop 拜訪過的 char 不會再進 while loop(可透過 DP 快速得到) - space:$O(n)$ ➔
tmp
,p
的長度 =2 * s.size() + 3