從0打卡leetcode之day 6--最長迴文串

帥地發表於2018-08-25

題目描述

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

示例1

輸入: "babad"
輸出: "bab"
注意: "aba"也是一個有效答案。

示例2

輸入: "cbbd"
輸出: "bb"

解題

對於這道題,最簡單的方法就是暴力求解了。對於很多演算法題,我想會暴力求解是最基本的能力,但也絕不能滿足於暴力,而且很多題的暴力解法都是很類似的。

這道題與其他的暴力解法一樣,外面兩層for迴圈遍歷找出所以子串,第三層迴圈用來判斷該子串是否為迴文串。
這種演算法的時間複雜度為O(n3)。這裡我就不給出程式碼了

優化策略

我們可以換一種思想,假如字串為迴文串,那麼把這個字串首尾兩個字元去掉,剩下的子串也會是一個迴文串。

基於這種想法,我們就可以這樣做了:一個for迴圈遍歷所有字元,單個字元也可以是一個迴文串,然後向這個字元的兩邊各自新增一個字元。判斷該字串是否還是迴文串。

例如a是一個迴文串,向a的兩邊新增一個字元,假如新增的這兩個字元相同的話,那麼新增之後的字串還是迴文串,如果兩個字串不同的話,那麼新增之後就不是字串了,。繼續遍歷下一個字元。,,,,,

需要注意的地方

不過這裡有一個需要注意的地方,我們上面是從單個字元的兩邊開始向兩邊擴充新增字元的,這種情況下,最終迴文串字元個數是奇數的,例如aba,cabac。

但是迴文串的字元個數也有可能是偶數的,例如bb,cbbc,那麼對於這種情況,按照單個字元向兩邊擴充的話就會出問題,因此對於這種情況,我們要從s[i],s[i+1]兩邊開始擴充。

知道了思路,可以自己先動手試一下能不能寫出來。

我做的程式碼去下:

    public String longestPalindrome(String s) {

        //先判斷是否為空或者長度小於1
        //把||寫成了&&害我找了好久都不知道錯在哪...
        if(s == null || s.length() < 1){
            return "";
        }
        int left = 0;//用來記錄子串的起始位置
        int right = 0;//用來記錄子串的末尾位置

        for(int i = 0; i < s.length(); i++){
            //通過findMore這個方法來擴充
            //bab這種情況
            int t1 = findMore(s, i, i);//bab這種情況
            //abba這種情況
            int t2 = findMore(s, i, i+1);

            //選出比較長的那個
            int max = Math.max(t1, t2);
            if(max > right - left){
                left = i - (max - 1)/2;
                right = i + max/2;
            }
        }
        return s.substring(left, right+1);
    }

    public int findMore(String s, int left, int right){
        while(left >= 0 && right < s.length()
                && s.charAt(left) == s.charAt(right)){
            left--;
            right++;
        }
        return right - left - 1;
    }

這種方法的時間複雜度為O(n2)。

不過我去看了官方的解答,那裡貌似提供了一個更牛的解法連結,這個解法的時間複雜度為O(n)。假如你有興趣的話,可以去研究下。

連結:https://articles.leetcode.com/longest-palindromic-substring-part-ii/

關注公我的眾號:苦逼的碼農,獲取更多原創文章,後臺回覆禮包送你一份特別的資源大禮包。同時也感謝把文章介紹給更多需要的人。。

相關文章