题目描述

给你一个字符串 s,找到 s 中最长的回文子串

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

 

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

 

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

题解

暴力解法

枚举所有子串

    public String longestPalindrome(String s) {
        int max = 0;
        String res = "";
        for (int i = 0; i < s.length(); i++) {
            for (int j = i; j < s.length(); j++) {
                String sub = s.substring(i, j + 1);
                if (checkPalindrome(sub) && sub.length() > max) {
                    max = sub.length();
                    res = sub;
                }
            }
        }
        return res;
    }
    public boolean checkPalindrome(String s) {
        int l = 0, r = s.length() - 1;
        while (l < r) {
            if (s.charAt(l) != s.charAt(r)) {
                return false;
            }
            else {
                l++;
                r--;
            }
        }
        return true;
    }
  • 时间复杂度:O(n³)
  • 空间复杂度:O(1)

正常解法1

枚举所有位置,以该位置作为中心从中间不断向两边扩展,依次判断,同时字符串长度为奇数和偶数的情况

    public String longestPalindrome(String s) {
        String res = "";
        int max = 0;
        for (int i = 0; i < s.length(); i++) {
            String str1 = findLongestStr(s, i, i);
            String str2 = findLongestStr(s, i, i + 1);
            if (Math.max(str1.length(), str2.length()) > max) {
                max = Math.max(str1.length(), str2.length());
                res = str1.length() > str2.length() ? str1 : str2;
            }
        }
        return res;
    }
    public String findLongestStr(String s, int l, int r) {
        while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
            l--;
            r++;
        }
        return s.substring(l + 1, r);
    }
  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)

正常解法2

一个回文子串,去掉两端后剩下的字符串也一定是子串,abcba -> bcb -> c,因此可以利用该状态转移方程使用动态规划,且单字符串一定为回文子串,双字符串直接比较,初始化完成后,用二维数组dp[i,j]表示s(i,j)是否为回文子串,如果是,那么dp[i-1,j+1]则只需判断s(i-1)和s(j+1)这两个字符是否相等

public String longestPalindrome(String s) {
        boolean[][] dp = new boolean[s.length()][s.length()];
        int start = 0, end = 0;
        int max = 0;
        for (int i = 0; i < s.length(); i++) {
            dp[i][i] = true;
        }
        for (int i = s.length() - 1; i >= 0; i--) {
            for (int j = i + 1; j < s.length(); j++) {
                if (j - i <= 2) {
                    dp[i][j] = s.charAt(i) == s.charAt(j);
                }
                else {
                    dp[i][j] = dp[i + 1][j - 1] && s.charAt(i) == s.charAt(j);
                }
                if (dp[i][j] && j - i + 1 > max) {
                    max = j - i + 1;
                    start = i;
                    end = j;
                }
            }
        }
        return s.substring(start, end + 1);
    }