1. 程式人生 > >【LeetCode】Longest Palindromic Substring 解題報告

【LeetCode】Longest Palindromic Substring 解題報告

DP、KMP什麼的都太高大上了,自己想了個樸素的遍歷方法。

【題目】

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

【思路】(應該算是O(n)吧)

從中間向兩端搜尋,分別找到以每個字母為中心的最長迴文子串,如果兩邊剩餘的元素已經比當前最長迴文子串的一半還短時,停止遍歷。

大家別看程式碼長,是為了便於理解的。

【Java程式碼】

public class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        if (s == null || len == 1){
            return s;
        } 
        
        String ret = "";
        int mid = len / 2;
        int i = 0;
        while (true) {
            //遍歷到s兩端時,如果以mid+i或mid-i為中心的最長迴文都不比當前最優解長,遍歷結束
            if (2*(len-(mid+i)) < ret.length() && 2*(mid-i+1) < ret.length()) {
                break;
            }
            String str1 = palindrome1(s, mid+i);
            String str2 = palindrome2(s, mid+i);
            String str3 = palindrome1(s, mid-i);
            String str4 = palindrome2(s, mid-i);
            if (str1.length() > ret.length()) {
                ret = str1;
            }
            if (str2.length() > ret.length()) {
                ret = str2;
            }
            if (str3.length() > ret.length()) {
                ret = str3;
            }
            if (str4.length() > ret.length()) {
                ret = str4;
            }
            i++;
        }
        
        return ret;
    }
    
    //找出s中以index為中心的aba型的迴文子串
    public String palindrome1(String s, int index) {
        String ret = "";
        int i = index, j = index;
        while (i>=0 && j<s.length()) {
            if (s.charAt(i) != s.charAt(j)) {
                break;
            }
            ret = s.substring(i, j+1);
            i--;
            j++;
        }
        return ret;
    }
    
    //找出s中以index和index+1為中心的abba型迴文子串
    public String palindrome2(String s, int index) {
        String ret = "";
        int i = index, j = index+1;
        while (i>=0 && j<s.length()) {
            if (s.charAt(i) != s.charAt(j)) {
                break;
            }
            ret = s.substring(i, j+1);
            i--;
            j++;
        }
        return ret;
    }
}

【分析】

後來在網上找了類似的解法。如 http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html ,為了不用區分aba型和abba型的迴文子串,構造了一個新的字串 t ,在兩端和每兩個字母之間插入一個特殊字元 ‘#’ ,這樣當以‘#’為中心的迴文子串就是我的程式碼中abba型子串。

我的程式碼與之相比還使用了一個小trick,即從中間向兩端遍歷,這樣如果中間已經有比較長的迴文子串了,那麼兩端比較偏的迴文子序列就可省去判斷。

一遍就AC了,後來比較了網上的解法,不禁為自己有點小激動呢~。

分析可能有誤,也許只是自我感覺良好,歡迎大家指正!