LeetCode - Longest Palindromic Substring

https://leetcode.com/problems/longest-palindromic-substring/

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.

这道题有两种解法:

第一种是从每个字母出发往两边,直到找到palindromic的边界为止,注意,如果相邻两个字符相同的话,那么需要考虑两种情况,以其中一个字符为中心展开,和以这两个字符为中心展开。

这种解法时间复杂度O(n^2),空间复杂度O(1)

第二种是DP,本来我想用一维DP做的,代码如下:

public class Solution {
    public String longestPalindrome(String s) {
        if(s==null || s.length()==0) return "";
        int max = 1;
        int start = 0;
        int end = 0;
        int[] longest = new int[s.length()];
        longest[0] = 1;
        for(int i=1; i<s.length(); i++){
            int j= i-longest[i-1]-1;
            if(j<0 || s.charAt(j)!=s.charAt(i)){
                longest[i] = 1;
                int iter = i-1;
                while(iter>=0 && s.charAt(iter)==s.charAt(i)){
                    longest[i]++;
                    iter--;
                }
            }
            else{
                longest[i] = longest[i-1]+2;
            }
            if(longest[i]>max){
                max = longest[i];
                start = i - longest[i]+1;
                end = i;
            }
        }
        return s.substring(start, end+1);
    }
}

但过不了如“bananas”这种case, 返回回来的是“ana”,因为此时只能记录以字母i结尾的最长字符串,所以到第二个a的时候,记录的是"ana",但到第二个n的时候,应该是"nan",但由于前面记录的是"ana",所以它只会考虑“ana”前面的是否是"n",只会在前面一个字符的最长palindrome的基础上增加。

因此我们需要二维数组来记录任何[i, j]之间是否是palindrome

下面的解释来自:http://fisherlei.blogspot.com/2012/12/leetcode-longest-palindromic-substring.html

"

定义函数
P[i,j] = 字符串区间[i,j]是否为palindrome.

首先找个例子,比如S="abccb",
    S=    a  b  c  c  b
Index = 0  1  2  3  4

P[0,0] =1  //each char is a palindrome
P[0,1] =S[0] == S[1]    , P[1,1] =1 
P[0,2] = S[0] == S[2] && P[1,1], P[1,2] = S[1] == S[2] , P[2,2] = 1
P[0,3] = S[0] == S[3] && P[1,2], P[1,3] = S[1] == S[3] && P[2,2] , P[2,3] =S[2] ==S[3],  P[3,3]=1       
......................
由此就可以推导出规律

P[i,j] = 1  if i ==j
        =  S[i] ==S[j]   if j = i+1
        =  S[i] == S[j] && P[i+1][j-1]  if j>i+1

"

注意这里DP的执行顺序,例如"abcde", 判读"abcde"时,需要知道"bcd"是否对称,所以,代码中外层循环是以i为结束符,内层循环是以从0 - i 字符为开始字符 的字符串,这样就可以保证在执行DP时,需要的结果已经先算出来了。时间复杂度O(n^2),空间复杂度O(n^2)

public class Solution {
    public String longestPalindrome(String s) {
        if(s==null || s.length()==0) return "";
        int max = 1;
        int start = 0;
        int end = 0;
        boolean[][] valid = new boolean[s.length()][s.length()];
        for(int i=0; i<s.length(); i++){
            for(int j=0; j<=i; j++){
                valid[j][i] = (s.charAt(i)==s.charAt(j) && (((i-j)<2) || valid[j+1][i-1]));
                if(valid[j][i] && max < (i-j+1)){
                    max = i-j+1;
                    start = j;
                    end = i;
                }
            }
        }
        return s.substring(start, end+1);
    }
}
下面还有一个O(n)的解法,用一位数组做的DP,不过没太看懂。。。。。有空再研究吧。。。。

http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

http://www.felix021.com/blog/read.php?2040

思路清晰真的太重要了,尤其是在设计DP算法的时候!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值