最長迴文子串

題目描述

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

示例1:

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

示例2:

輸入:“bcbbd”
輸出:“bb”

解題思路

思路一:取出所有子串,在子串中找最長迴文子串

  迴文字符串:正讀和倒讀都是一樣的順序的字符串就是迴文字符串。那如何判斷最長迴文子串呢?我們可以理解,就是判斷一個字符串的所有子串中,是最長的迴文子串。那麼我們就有了一個解題思路:取出字符串中的所有子串判斷其是否迴文,如果迴文的話判斷其是否是最長的迴文子串。
在這裏插入圖片描述
就有了下面的代碼:

class Solution {
    public String longestPalindrome(String s) {
        // 迴文子串:正讀和反讀都一樣
        // 最長的迴文子串:取出字符串中所有的子串進行判斷是否是迴文子串
        
        // 直接返回的情況:字符串的長度小於2
        if(s.length() < 2)
            return s;
        
        String result = s.substring(0, 1);  // 用於保存返回的字符串
        String tmp = null;
        String tmp_R = null;
        // 截取所有的子串進行比較
        for(int i = 0; i < s.length()-1; ++i){
            tmp = null;
            tmp_R = null;
            for(int j = s.length(); j > i; --j){
                // 1. 先截取一個字符串,如果截取的子串沒有當前的子串大,就不截取了
                if(j - i > result.length()){
                    tmp = s.substring(i, j);
                    // 2. 翻轉字符串
                    tmp_R = new StringBuffer(tmp).reverse().toString();
                    // 3. 如果兩個子串相同,則將其賦值給result字符串
                    if(tmp.equals(tmp_R) && tmp.length() > result.length()){
                        result = tmp;
                    }
                }
            }
        }
        
        return result;
    }
}

當我們在leetcode上的在線oj上運行的時候,會發現這種思路是正確的的,但是當遇到較長字符串的時候會超出時間限制,說明這種方法還是不夠優化,只是最基礎的代碼實現。

思路二:中心擴展算法

  觀察迴文子串,我們會發現迴文子串有一個很奇妙的特點,它可以按照它的中心去展開,它按照中心是一一對應的。
在這裏插入圖片描述
通過上面的圖示,我們會發現出現兩種情況,奇數個字符的子串和偶數個字符的子串,他們的情況有些許的不同。由於需要從每個字符開始擴展尋找,我們將該思想寫成一個方法去實現。
在這裏插入圖片描述
  我們要實現上述方法的迴文子串,就需要將我們的字符串傳遞,還需要將中心的位置傳遞過去,奇數個的話,傳遞兩個相同的位置;偶數個的話,傳遞兩個緊挨的位置,便於判斷,由於我們不能確定從該字符出擴展,到底有奇數個字符的迴文子串還是偶數個字符的迴文子串,所以我們兩個都要去進行處理。
  在找回文子串的時候,我們只需要找到中心位置和迴文子串的長度就可以確定迴文子串啦!!!
代碼實現:

class Solution {
    public String longestPalindrome(String s) {
        // 長度爲1的字符串本就是迴文字符串
        if(s.length() < 2)
            return s;
        // 使用中心擴展算法向兩邊擴展尋找回文子串,一直找到沒有相同的爲止,但是會出現偶數的子串
        int center = 0; // 標記迴文子串的中位置
        int maxLength = 0;  // 標記迴文子串的長度
        
        for(int i = 0; i < s.length(); i++){
            int oddLength = centerString(s, i, i); // 最長迴文子串爲奇數
            int evenLength = centerString(s, i, i+1);   // 最長迴文子串爲偶數
            
            // 判斷最長迴文子串爲奇數或爲偶數的情況
            if(maxLength < Math.max(oddLength, evenLength)){
                center = i;
                maxLength = Math.max(oddLength, evenLength);
            }
        }
        // 截取回文子串
        return s.substring(center-(maxLength - 1)/2, center+maxLength/2+1);
    }
    // 返回最長迴文子串的長度
    private int centerString(String s, int left, int right){
        int begin = left;
        int end = right;
        
        // 找出迴文子串
        while(begin >= 0 && end < s.length() && s.charAt(begin) == s.charAt(end)){
            begin--;
            end++;
        }
        // 找到迴文子串的長度,並返回
        return end - begin - 1;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章