5. Longest Palindromic Substring



July-12-2019
前面123刷逼逼一大堆什么亂七八糟的。。
暴力O(nn)

class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.length() <= 1) return s;
        String res = "";
        for (int i = 0; i < s.length(); i ++) {
            String tempStr = getPalindrome(i, i, s);
            if (tempStr.length() > res.length()) {
                res = tempStr;
            }
            tempStr = getPalindrome(i, i + 1, s);
            if (tempStr.length() > res.length()) {
                res = tempStr;
            }
        }
        
        return res;
    }
    
    public String getPalindrome(int l, int r, String s) {
        while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
            l --;
            r ++;
        }
        return s.substring(l + 1, r);
    }
}

上來就覺得是動態規划,然后慘遭打臉,動態規划不是最優解。

其實可以理解,因為動態規划里,內層循環的String長度是從大到小,一旦發現Palindrome,那么此時內層循環的最長回文數列已經確定,按理說可以break.可是,沒進行判斷的部分以后可能被用到,所以沒法BREAK。。

public class Solution 
{
    public String longestPalindrome(String s) 
    {
        if(s.length() <= 1) return s;
        
        boolean[][] P = new boolean[s.length()][s.length()];
        String res = new String();
        for(int i = 0; i < s.length();i++) P[i][i] = true;
        int max = 0;
        for(int i = 0; i < s.length();i++)
        {
            for(int j = 0; j < i; j++)
            {
                P[j][i] = (s.charAt(j) == s.charAt(i) && (i-j <= 2 || P[j+1][i-1]));
                if(P[j][i])
                {
                    if(i-j + 1 > max)
                    {
                         max = i-j+1;
                         res = new String(s.substring(j,i+1));
                    }
                    
                                      
                }
                
            }
        }
        
        return res;
        
        
    }

}

正確的做法是backtrack. 回文判斷從中間判斷比較划算,因為一旦失敗,就沒有繼續往外判斷的意義了,可以back track。

所以就遍歷,從遍歷的位置為中心往兩邊判斷。

需要注意,ABA ABBA這倆都算回文,第一個中心是B,第二個是BB(也可以看做是BB之間的空隙)。

所以遍歷的時候,每個位置要先以當前字母為中心,再以當前字母和他右邊那個為中心。。

public class Solution 
{

    public String longestPalindrome(String s) 
    {
       if(s.length() <= 1) return s;
       
       int max = 0;
       String res = new String();
       
       for(int i = 0; i < s.length();i++)
       {
           int L = i, R = i;
           String temp = getPlength(s,L,R);
           if(temp.length() > max)
           {
               max = temp.length();
               res = new String(temp);

           }

           if(i != s.length() - 1)
           {
               L = i; R = i + 1;
               temp = getPlength(s,L,R);
               if(temp.length() > max)
               {
                   max = temp.length();
                   res = new String(temp);
               }
           }
           
       }
       
       return res;
     
    }
    
    
    public String getPlength(String s, int L , int R)
    {

        
        while(L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R))
        {
            L--;R++;
        }
        
        return s.substring(L+1,R);
    }

}

時間上確實比DP要快。

然后又打臉了,發現答案里還有個O(n)的辦法。。。
上面2個都是n²:
第一個沒剪枝,用動態規划保存一些數據,不用每次判斷回文。
第二個剪枝,但是每次必須重新判斷回文,好在是從里往外,很容易break.

O(N)的還沒看。。下次刷再說吧。。
放個O(N)的傳送門

http://articles.leetcode.com/longest-palindromic-substring-part-ii)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM