LeetCode_Medium_5. Longest Palindromic Substring

2019.1.22

题目描述:

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"

这题是求字符串的最长回文子串,回文串其实可以理解为对称串,但不是普遍意义上的对称,比如bd,而是字符相同,如bb,这点需要搞清楚,本题最长回文子串就是求回文子串中最长的。

解法一:

从字符串开头到字符串结尾以每个字符为中心,向两边扩散,也是类似窗口模式,但是是扩大窗口而不是滑动窗口。若窗口的边界字符相同,那就继续扩大,若不相同,就移到下个字符重新开始扩散。这里需要注意区分字符串的长度是奇数还是偶数,若是奇数,那中心的字符是不需要比较的,直接比较中心字符的左字符与右字符,若是偶数,则需要将该中心字符与其下一个字符均作为中心字符,先比较再扩散。比如说"bab"与"abba"

C++代码:

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.size()<=1) return s;
        int len=s.size(),maxlen=0,begin=0;
        for(int i=0;i<len-1;i++){
            searchPal(s,i,i,begin,maxlen);
            searchPal(s,i,i+1,begin,maxlen);
        }
        return s.substr(begin,maxlen);
    }
    void searchPal(string s,int left,int right,int& begin,int& maxlen){
        while(left>=0&&right<s.size()&&s[left]==s[right]){
            left--;
            right++;
        }
        if(maxlen<right-left-1){
            begin=left+1;
            maxlen=right-left-1;
        }
    }
};

Java代码:

public String longestPalindrome(String s) {
    if (s == null || s.length() < 1) return "";
    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^2),空间复杂度为O(1)。

解法二:

官方解法:

解法三:

官方解法:

这里我们维护一个二维数组dp,其中dp[i][j]表示字符串区间[i, j]是否为回文串,当i = j时,只有一个字符,肯定是回文串,如果i = j + 1,说明是相邻字符,此时需要判断s[i]是否等于s[j],如果i和j不相邻,即i - j >= 2时,除了判断s[i]和s[j]相等之外,dp[j + 1][i - 1]若为真,就是回文串,通过以上分析,可以写出递推式如下:

dp[i, j] = 1                                               if i == j

           = s[i] == s[j]                                if j = i + 1

           = s[i] == s[j] && dp[i + 1][j - 1]    if j > i + 1      

C++代码:

class Solution {
public:
    string longestPalindrome(string s) {
        if (s.empty()) return "";
        int dp[s.size()][s.size()] = {0}, left = 0, right = 0, len = 0;
        for (int i = 0; i < s.size(); ++i) {
            for (int j = 0; j < i; ++j) {
                dp[j][i] = (s[i] == s[j] && (i - j < 2 || dp[j + 1][i - 1]));
                if (dp[j][i] && len < i - j + 1) {
                    len = i - j + 1;
                    left = j;
                    right = i;
                }
            }
            dp[i][i] = 1;
        }
        return s.substr(left, right - left + 1);
    }
};

解法四:终极大招

Manacher 算法(马拉车算法),官方给出的链接https://articles.leetcode.com/longest-palindromic-substring-part-ii/ 出现了Error establishing a database connection,数据库连接失败,也不知道什么时候回修复,所以我就自己查询了一下相关博客,详见博客 http://www.cnblogs.com/grandyang/p/4475985.html,该算法可以将时间复杂度变为线性即O(n),很强大

猜你喜欢

转载自blog.csdn.net/weixin_41637618/article/details/86588934