LeetCode 05 Longest Palindromic

2016-04-15  本文已影响129人  SiyueLin

题目要求

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.
  题目翻译:给定一个字符串,找到最长的回文字串,假定字符串长度最大为1000,并存在唯一的最大回文子串。

题目分析一

假设s(j+1,k-1)是一个回文串,且s[j]==s[k],可证,s(j,k)也一定是一个回文串。由此启发,我们可以记录之前的结果作为启发信息,以利于后面的判断和搜索。该算法的复杂度为O(n^2)。

package com.linsiyue;

public class Solution {
    public String longestPalindrome(String s) {
        int n = s.length();
        int lo = 0,maxLen = 0;
        // 声明一个boolean型二维数值,s(j,k)为回文串则boolean[i][j]=true
        // 其中 i<=j
        boolean[][] dp = new boolean[n][n];
        for (int i = n-1; i >= 0; i--) {
            for (int j = i; j < n; j++) {
                // 关键点是j-i<3这个边界条件的加入,搜索问题要定义明确边界条件
                // 当字符串长度为1或i=0时,dp[i+1][j-1]会出现数组越界的错误
                // 当s.charAt(i)==s.charAt(j) && j-i<3 时,是回文串,如aba,aa
                dp[i][j] = s.charAt(i)==s.charAt(j) && (j-i<3 ||dp[i+1][j-1]);
                if (dp[i][j] && j-i+1>maxLen){
                    lo = i;
                    maxLen = j-i+1;
                }
            }
        }
        return s.substring(lo,lo+maxLen);
    }
}

题目分析二

长度为偶数的回文串,有如下性质:中间的两个字符s[i]==s[i+1],且s[i-1]==s[i+2],依次向两边对称递推,直到碰到回文串边界。长度为奇数的回文串,最中间的数的两边的数相等,即s[i-1]==s[i+1],隐含着一个重要条件,s[i]==s[i],有了该隐含条件,递推模式即如偶数。
  因此奇偶数情况可以抽象为一个模型:由中间向两边,依次比较轴对称的两个字符,直到两个字符不相等,即可获得该回文串的起始地址及长度。
  函数extendPalindrome(String s, int j, int k)即是该模型的实现。

package com.linsiyue;

public class Solution {
    private int lo, maxLen;
    public String longestPalindrome(String s) {
        int len = s.length();
        if (len<2)
            return s;
        for (int i = 0; i < len-1; i++) {
            // 奇数情况
            extendPalindrome(s,i,i);
            // 偶数情况
            extendPalindrome(s,i,i+1);
        }
        return s.substring(lo, lo+maxLen);
    }   
    public void extendPalindrome(String s, int j, int k) {
        while (j>=0 && k<s.length() && s.charAt(j)==s.charAt(k)){
            j--;
            k++;
        }
        // 跳出while循环时,回文串的开头和结尾游标分别被-1和+1
        // 因此计算长度的补回:len=(k-1)-(j+1)+1=k-j-1
        if(maxLen < k-j-1){
            lo = j+1;
            maxLen = k-j-1;
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读