1. 程式人生 > 其它 >leetcode 5/300 最長迴文子串 py

leetcode 5/300 最長迴文子串 py

目錄

題目說明

要看明白求得是什麼,最長迴文字串是指例如cababa中ababa是最長的,不是求迴文的部分aba

方法一:動態規劃——狀態轉移方程

動態規劃的要素

  1. 如果可以把區域性子問題的解結合起來得到全域性最優解,那這個問題就具備最優子結構 ;

  2. 如果計算最優解時需要處理很多相同的問題,那麼這個問題就具備重複子問題。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        
        size = len(s)
        # 特殊處理
        if size == 1:
            return s
        # 建立動態規劃dynamic programing表
        dp = [[False for _ in range(size)] for _ in range(size)]
        #建立了一個5x5的,初始化為false的矩陣,false代表不是字串部分
        # 初始長度為1,這樣萬一不存在迴文,就返回第一個值(初始條件設定的時候一定要考慮輸出)
        max_len = 1
        start = 0
        for j in range(1,size):
            for i in range(j):
                # 邊界條件:
                # 只要頭尾相等(s[i]==s[j])就能返回True
          '''''
          第一個if else是為了判斷迴文字串中是否有其他相等的部分,當小於2如aba,明顯不存在,所以可以直接設為true
          當大於2,如ababa當判斷第一個a和最後一個a時,需要在判斷兩個b是否相同。
          '''''
                if j-i<=2:
                    if s[i]==s[j]:
                        dp[i][j] = True
                        cur_len = j-i+1
                # 狀態轉移方程 
                # 當前dp[i][j]狀態:頭尾相等(s[i]==s[j])
                # 過去dp[i][j]狀態:去掉頭尾之後還是一個迴文(dp[i+1][j-1] is True)
                else:
                    if s[i]==s[j] and dp[i+1][j-1]:
                        dp[i][j] = True
                        cur_len = j-i+1
                # 出現迴文更新輸出
                if dp[i][j]:
                    if cur_len > max_len:
                     #這裡判斷是否為最長的迴文字串如abab有兩個結果時,只會選擇輸出第一個最長的aba
                        max_len = cur_len
                        start = i

        return s[start:start+max_len]
'''
作者:_Breiman
連結:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/5-zui-chang-hui-wen-zi-chuan-dong-tai-gu-p7uk/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
'''

方法二:優化中心擴充套件演算法

思路:首先,我們進行拆解,從簡單到複雜

  1. 考慮中心到兩邊的數都等於中心,這樣只需要考慮一邊的情況,最後左右兩邊相減,得到最長
  2. 考慮兩邊不等於中心,需要考慮左邊是否等於右邊
  3. 對每次迴圈得到的最長子串進行判斷,如果比上一次的長,則替換
    簡而言之,就是找到一個i,從i依次向左向右判斷是否相同。

#優化中心擴充套件演算法以及由簡單到全面的思路
class Solution:
    def longestPalindrome(self, s: str) -> str:
        # 長度為0 或者1時,直接返回原序列
        if len(s) < 2:
            return s
        maxstr = ''
        # 定義兩個指標,一左一右
        left = 0
        right = 0
        for i in range(len(s)):
            left = i - 1
            right = i + 1
            while left > -1 and s[left] == s[i]:
                left -= 1
            while right < len(s) and s[right] == s[i]:
                right+=1
            while left>-1 and right<len(s) and s[left] == s[right]:
                left -= 1
                right += 1
            #這裡邊界需要注意,跳出迴圈的時候指標都超過範圍了需要縮小,但是切片右邊界不包括,因此需要加一,所以抵消
            maxstr = s[left+1:right] if right-left-1>len(maxstr) else maxstr
            '''
            可以看出,如果沒有最長字串,那麼最後會返回第一個字元。並且由於前面第三個while減一了,所以這裡要加一,並且由於左閉右開,所以right不用變
            '''
        return maxstr
'''
作者:6GU30N7ObH
連結:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/you-hua-zhong-xin-kuo-zhan-suan-fa-yi-ji-p30u/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
'''

本文來自部落格園,作者:xyzhrrr,轉載請註明原文連結:https://www.cnblogs.com/xyzhrrr/p/15451124.html