LeetCode - Longest Palindromic Substring

来源:互联网 发布:淘宝宝贝介绍图拉伸了 编辑:程序博客网 时间:2024/05/20 07:36

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
原创粉丝点击