[LeetCode解題攻略] 5. Longest Palindromic Substring

更新於 2024/12/04閱讀時間約 8 分鐘

這篇文章要解說的是 LeetCode 題目 5. Longest Palindromic Substring,這是一道典型的字串題,重點在於找出輸入字串中的最長回文子字串。下面是這篇解題教學的詳細分析與多種解法,讓你能全面掌握這題的技巧。


題目概述

給定一個字串 s,我們需要找出其中最長的回文子字串。如果字串是空的,可以直接返回空字串。回文是指正讀與反讀相同的字串。例如,"aba" 和 "racecar" 都是回文。


思路與解法

這道題有多種解法,從基礎到進階,我們可以逐步優化以降低時間複雜度。以下列出三種常見的解法:

  1. 暴力解法 (Brute Force)
  2. 中心擴展法 (Expand Around Center)
  3. 動態規劃法 (Dynamic Programming)

解法一:暴力解法 (Brute Force)

這是最直接的方式,透過遍歷所有可能的子字串並檢查每個子字串是否為回文。若是回文,則更新最長回文的紀錄。這樣的解法較為簡單易懂,但時間複雜度較高。

步驟:

  1. 從頭遍歷字串 s,並考慮所有可能的子字串。
  2. 檢查每個子字串是否為回文。
  3. 如果找到的回文子字串比當前記錄的最長回文長,就更新最長回文。

實作 (Python):

class Solution:
def longestPalindrome(self, s: str) -> str:
longest = ""
for i in range(0, len(s)):
for j in range(i, len(s)):
substring = s[i:j + 1]
if (substring == substring[::-1]) and (len(substring) > len(longest)):
longest = substring
return longest

複雜度分析:

  • 時間複雜度:O(n^3)(因為有兩層迴圈加上判斷回文的額外操作)
  • 空間複雜度:O(1)

暴力解法的時間複雜度過高,因此僅適用於較短的字串。接下來介紹更高效的解法。


解法二:中心擴展法 (Expand Around Center)

回文子串具有對稱性,因此可以從每個可能的中心點開始,嘗試向外擴展來找出最長的回文子串。

步驟:

  1. 從每個位置開始,將它視為回文的中心點。
  2. 對於每個中心點,從該點向兩側擴展,找到最長的回文。
  3. 如果擴展得到的回文比目前記錄的最長回文長,則更新最長回文。

注意:回文中心可能是單個字元(奇數長度回文)或兩個字元(偶數長度回文)。

實作 (Python):

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

def expand_around_center(s, left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return s[left + 1:right]

longest = ""
for i in range(0, len(s)):
# 奇數長度的回文
odd_palindrome = expand_around_center(s, i, i)
# 偶數長度的回文
even_palindrome = expand_around_center(s, i, i + 1)

# 更新最長回文
longest = max(longest, odd_palindrome, even_palindrome, key=len)

return longest

複雜度分析:

  • 時間複雜度:O(n^2)(擴展操作最壞情況下需要 O(n),每次擴展的操作有 O(n) 個中心)
  • 空間複雜度:O(1)

中心擴展法已經能夠處理長度較大的字串,且效果不錯。接著,我們會討論時間複雜度更優化的解法。


解法三:動態規劃法 (Dynamic Programming)

這是一種進階解法,利用動態規劃表格來儲存回文資訊,以避免重複計算。

步驟:

  1. 建立一個二維布林陣列 dp,其中 dp[i][j] 表示字串 s[i:j+1] 是否為回文。
  2. s[i] == s[j] 且子串 s[i+1:j-1] 也是回文,則 s[i:j+1] 也是回文。
  3. 每當找到較長的回文子串時,就更新最長回文的紀錄。

實作 (Python):

class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
if n == 0:
return ""

dp = [[False] * n for _ in range(n)]
start, max_length = 0, 1

for i in range(n):
dp[i][i] = True

for length in range(2, n + 1): # length of the substring
for i in range(n - length + 1):
j = i + length - 1
if s[i] == s[j]:
if length == 2 or dp[i + 1][j - 1]:
dp[i][j] = True
if length > max_length:
start, max_length = i, length

return s[start:start + max_length]

複雜度分析:

  • 時間複雜度:O(n^2)
  • 空間複雜度:O(n^2)(需要存儲所有子串的狀態)

動態規劃法雖然空間複雜度較高,但在實際操作中,對於長字串其效率表現良好,特別是在需要找出所有回文子字串的情況下。


結語

在處理這類字串問題時,不同解法各有其適用的場景。以下是三種解法的適用情境:

  • 暴力解法:適合入門理解,僅適用於小規模的輸入。
  • 中心擴展法:大多數場景下的理想解法,性能和代碼簡潔性都很好。
  • 動態規劃法:適合更大的數據規模,並適用於需要判斷多個回文子串的情境。

希望這篇解題教學能幫助你更好地掌握 Longest Palindromic Substring 這道題目!

歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
給定兩個已排序的陣列 nums1 和 nums2,請找到並返回這兩個陣列的中位數。要求時間複雜度為 O(log(min(m, n))),其中 m 和 n 分別是兩個陣列的長度。
給定一個字串 s,請找出其中不含重複字母的最長子字串的長度。
在這篇文章中,我們將深入探討 LeetCode 題目「2. Add Two Numbers」的解法。這道題目考察對鏈結串列 (Linked List) 操作和進位處理的掌握。
在 LeetCode 上,Two Sum 這道題目主要考察如何高效地處理數組和數據查找問題,是面試中常見的問題之一。今天我們將詳細解說這道題目,並提供幾種解題方法。
給定兩個已排序的陣列 nums1 和 nums2,請找到並返回這兩個陣列的中位數。要求時間複雜度為 O(log(min(m, n))),其中 m 和 n 分別是兩個陣列的長度。
給定一個字串 s,請找出其中不含重複字母的最長子字串的長度。
在這篇文章中,我們將深入探討 LeetCode 題目「2. Add Two Numbers」的解法。這道題目考察對鏈結串列 (Linked List) 操作和進位處理的掌握。
在 LeetCode 上,Two Sum 這道題目主要考察如何高效地處理數組和數據查找問題,是面試中常見的問題之一。今天我們將詳細解說這道題目,並提供幾種解題方法。
你可能也想看
Google News 追蹤
Thumbnail
徵的就是你 🫵 超ㄅㄧㄤˋ 獎品搭配超瞎趴的四大主題,等你踹共啦!還有機會獲得經典的「偉士牌樂高」喔!馬上來參加本次的活動吧!
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
題目敘述 Longest Arithmetic Subsequence of Given Difference 給定一個整數陣列nums,請找出給定公差difference的最長的等差數列的長度是多少?
Thumbnail
題目敘述 Longest Palindromic Subsequence 給定一個字串s,請找出字串s的最長回文子序列的長度。 註: 子序列 不要求一定要連續。 測試範例 Input: s = "bbbab" Output: 4
Thumbnail
題目敘述 Longest Palindromic Substring 給定一個輸入字串s,請找出最長的回文子字串。 答案可能不只一個,回傳任何一個合法的答案皆可。
Thumbnail
給定兩個輸入整數陣列, 若在兩個陣列遇到相同的數字可以連成一線, 但是有規定連線不可和別的連線有交叉, 請問最多可以形成幾條連線? 解答中探討了演算法化簡的技巧和DP模型, 可以透過演算法化簡的技巧, 把這題映射到原本已經學會的Longest Common Subsequence的DP模型來解開。
Thumbnail
給定一個字串s,以s擁有的字元製造迴文字串。要能製造出的迴文字串長度最長是多少,觀察迴文字串不外乎兩種模式對稱部分 + 核心字元 + 對稱部分,其中,核心字元在正中央出現一次,或者 對稱部分 + 對稱部分。使用演算法統計出現次數並推理出盡可能充分利用每個字元的迴文字串製造方法。
Thumbnail
Append Characters to String to Make Subsequence 給定兩個字串s和字串t。 請計算最少的字元串接數量是多少,串接在s的尾端,使得t是s的子序列。 測試範例 Example 1: Input: s = "coaching", t =
Thumbnail
這題也是滿經典的DP動態規劃教學案例和題目,就順便複習一下吧。 題目敘述 題目會給我們兩個字串text1, text2。 要求我們找出兩個字串的最長共同子序列,並且返回最長共同子序列的長度。 如果彼此沒有共同子序列,則返回0。 題目的原文敘述 測試範例 Example 1: In
Thumbnail
題目敘述 題目會給定我們兩個字串word1 和 word2。 允許我們不限制次數進行下列兩種操作: 任意調換其中兩個字元的位置。 把字串中的某個字元全部置換成另一個字元,同時把另一個字元同時置換成某個字元。(例如把字串中原本的a都換成b,把原本的b都換成a) 問我們能不能通過上述兩項操作,
Thumbnail
徵的就是你 🫵 超ㄅㄧㄤˋ 獎品搭配超瞎趴的四大主題,等你踹共啦!還有機會獲得經典的「偉士牌樂高」喔!馬上來參加本次的活動吧!
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
題目敘述 Longest Arithmetic Subsequence of Given Difference 給定一個整數陣列nums,請找出給定公差difference的最長的等差數列的長度是多少?
Thumbnail
題目敘述 Longest Palindromic Subsequence 給定一個字串s,請找出字串s的最長回文子序列的長度。 註: 子序列 不要求一定要連續。 測試範例 Input: s = "bbbab" Output: 4
Thumbnail
題目敘述 Longest Palindromic Substring 給定一個輸入字串s,請找出最長的回文子字串。 答案可能不只一個,回傳任何一個合法的答案皆可。
Thumbnail
給定兩個輸入整數陣列, 若在兩個陣列遇到相同的數字可以連成一線, 但是有規定連線不可和別的連線有交叉, 請問最多可以形成幾條連線? 解答中探討了演算法化簡的技巧和DP模型, 可以透過演算法化簡的技巧, 把這題映射到原本已經學會的Longest Common Subsequence的DP模型來解開。
Thumbnail
給定一個字串s,以s擁有的字元製造迴文字串。要能製造出的迴文字串長度最長是多少,觀察迴文字串不外乎兩種模式對稱部分 + 核心字元 + 對稱部分,其中,核心字元在正中央出現一次,或者 對稱部分 + 對稱部分。使用演算法統計出現次數並推理出盡可能充分利用每個字元的迴文字串製造方法。
Thumbnail
Append Characters to String to Make Subsequence 給定兩個字串s和字串t。 請計算最少的字元串接數量是多少,串接在s的尾端,使得t是s的子序列。 測試範例 Example 1: Input: s = "coaching", t =
Thumbnail
這題也是滿經典的DP動態規劃教學案例和題目,就順便複習一下吧。 題目敘述 題目會給我們兩個字串text1, text2。 要求我們找出兩個字串的最長共同子序列,並且返回最長共同子序列的長度。 如果彼此沒有共同子序列,則返回0。 題目的原文敘述 測試範例 Example 1: In
Thumbnail
題目敘述 題目會給定我們兩個字串word1 和 word2。 允許我們不限制次數進行下列兩種操作: 任意調換其中兩個字元的位置。 把字串中的某個字元全部置換成另一個字元,同時把另一個字元同時置換成某個字元。(例如把字串中原本的a都換成b,把原本的b都換成a) 問我們能不能通過上述兩項操作,