5. 最长回文子串(Longest Palindromic Substring)

题目描述

       给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 长度最长为1000。

       回文串是指正读和反读都一样的字符串。

解题思路及实现

方法一:最长公共子串

       反转S,变成T,S与T的最长公共子串Y就是最长回文子串。

       当S="abacdfgdcaba"时,T="abacdgfdcaba",Y="abacd",很明显Y不是回文串。

       该如何解决?

       每当我们找到一个最长的公共子串的时候,要检查其是否是回文串。

方法二:暴力解决(超时)

       枚举子字符串所有可能的开始和结束位置,并验证其是否是回文串,找到里面最长的;

时间和空间复杂度

       时间复杂度为O(n*n*n),n为字符串的长度,会有(2n)个子字符串,验证每个子字符串是否是回文需要O(n)

       空间复杂度为O(1)

方法三:动态规划

      优化方法二,我们可以在验证子字符串是否是回文串时避免不必要的重新计算。

      对于子字符串"ababa",如果我们知道"bab"是一个回文,很明显左右字母相同,所以,"ababa"是一个回文串;

5. 最长回文子串(Longest Palindromic Substring)_第1张图片

       所以,在这种情况下,我们可以采用递归的方式解决问题。我们先初始化所有一个字母的回文串和两个字母的回文串,并找出所有三个字母的回文串,以此类推。

时间和空间复杂度

       时间复杂度为O(n*n),n为字符串的长度,会有(2n)个子字符串,验证每个子字符串是否是回文需要O(n)

       空间复杂度为O(n*n),用来存储表;

方法四:展开中心

       一个回文串是关于中心对称的,所以,可以从中心向两边扩展,一共有2n-1个中心。

       为什么是2n-1个,而不是n个?因为回文中心可以在两个字母之间(例如,abba)。

public String longestPalindrome(String s) {
    int start = 0, end = 0;
    for (int i = 0; i < s.length(); i++) {
        int len1 = expandAroundCenter(s, i, i);
        int len2 = expandAroundCenter(s, i, i + 1);
        int len = Math.max(len1, len2);
        if (len > end - start) {
            start = i - (len - 1) / 2;
            end = i + len / 2;
        }
    }
    return s.substring(start, end + 1);
}

private int expandAroundCenter(String s, int left, int right) {
    int L = left, R = right;
    while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
        L--;
        R++;
    }
    return R - L - 1;
}

时间和空间复杂度

       时间复杂度为O(n*n),n为字符串的长度,围绕其中心扩展需要O(n),总共有2n-1个中心;

       空间复杂度为O(1)

方法五:Manacher算法

       这是一个O(n)的算法, 详情




 

你可能感兴趣的:(LeetCode,LeetCode刷题指南)