拿什麼拯救你,我的面試!(從零打卡刷Leetcode——No.005)

小詹學Python發表於2018-06-08

寫在前邊:

小詹此記錄貼的讀者越來越少了,也許是小詹總結的不夠好歡迎留言區提出寶貴的意見!也歡迎和小詹一起定期刷leetcode,每週一和週五更新一題,每一題都吃透,歡迎一題多解,尋找最優解!這個記錄帖哪怕只有一個讀者,小詹也會堅持刷下去的!


                                               No.5 最大回文子串

原題:(有中文網站,就不去讀英語啦哈哈)

給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為1000。

例如:

#示例一
輸入: "babad"
輸出: "bab"
注意: "aba"也是一個有效答案。
#示例二
輸入: "cbbd"
輸出: "bb"複製程式碼

思路分析:這題難度官網給出的是中等難度,小詹自己做的時候卻花了很久,學習之路還有很遠啊~看到這個題目,小詹是想著先找到所有存在的迴文子串,之後比較長度,輸出最長的子串。動筆根據所給案例進行了比劃,發現一個很關鍵的點!最長迴文子串的中間子串也是迴文串,換言之,迴文串是否最長,可以看回文串兩邊的字元是否相同。例如“dabcba”的最長迴文子串是“abcba”,其可看出迴文子串“bcb”的擴充,判斷“bab”兩邊的字元是否相同決定是否進行迴文子串擴充(可以利用切片的索引左右移動實現)

排坑!小詹覺得這個思路不錯,就按照思路進行了實現,程式碼是下面這樣子的(有雷坑噢)

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        #小詹提示:這種題要注意特例,單字元本身就是自己的最大回文子串噢
        if len(s) < 2:
            return s
        #定義待返回的字串
        self.res = ""
        for i in range(len(s)):
            #遍歷假設每一個字元為迴文字元中心,向兩端擴充判斷,left,right,記錄字串左右索引
            left = right = i
            #這裡是判斷當前迴文子串兩端相同的時候,向兩端擴充
            while left>=0 and right < len(s) and s[left] == s[right]:
                left -= 1
                right += 1
            #這裡的right-left-1是當前的迴文子串長度,大於歷史最大值,就更新最大值
            if right -left -1 > len(self.res):
                self.res = s[left+1:right]
        return self.res
複製程式碼

嗯~小夥伴感興趣可以將程式碼提交試試看,只能通過部分樣例測試。為什麼呢?小詹提交後發現類似示例2“cbbd”這種會出錯!找到了錯誤就好分析了,是因為上邊的程式碼預設從同一個字元位置向兩端擴充,然而類似“cbbd”這種測試用例,是從相鄰兩個字串位置進行擴充,所以我們可以兩種情況都考慮進去,最後選擇最長的,考慮到這之間有相同的操作,為程式碼整潔,將其模組化分割出一個函式,程式碼如下:

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        #小詹提示:這種題要注意特例,單字元本身就是自己的最大回文子串噢        
        if len(s) < 2:
            return s
        #定義待返回的字串
        self.res = ""
        for i in range(len(s)):
            #這裡就是考慮到兩種情況,從相同字元拓寬和從相鄰字元拓寬
            self.helper(s, i, i)
            self.helper(s, i, i+1)
        return self.res
    
    #分割出來的相同操作函式! 
    def helper(self,s, left, right):
        #這裡是判斷當前迴文子串兩端相同的時候,向兩端擴充
        while left>=0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
            #這裡的right-left-1是當前的迴文子串長度,大於歷史最大值,就更新最大值
        if right -left -1 > len(self.res):
            self.res = s[left+1:right]
複製程式碼

給出執行結果之前,有必要關於self說幾句,之前也有小夥伴群裡問過,這裡給出幾句話:

  1. self 不是一個關鍵詞,可以替換成其他(比如this),只是習慣用self

  2. self不是指向類本身,而是指向類例項物件(比如class person() a = person('xiaozhan'),這時self會指向例項person類的例項類物件a)

完整程式碼執行結果如下:(小詹是中文網站看題,英文網站提交)

                    拿什麼拯救你,我的面試!(從零打卡刷Leetcode——No.005)

往期推薦

【記錄帖】(No.001)從零打卡刷Leetcode

【記錄帖】(No.002)從零打卡刷Leetcode

【記錄帖】(No.003)從零打卡刷Leetcode

【記錄帖】(No.004)從零打卡刷Leetcode


歡迎掃碼關注微信公眾號,和小詹一起愉快的學習玩耍噢~

拿什麼拯救你,我的面試!(從零打卡刷Leetcode——No.005)


相關文章