(LeetCode)Java 求解最长回文子串

217 阅读2分钟

一、题解

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

示例1:

输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。

示例2:

输入: "cbbd" 输出: "bb"


暴力解法,会超时,需要考虑动态规划,

动态规划参考:什么是动态规划

思路就是创建一个二维数组,boolean[][] flag, flag[i][j] 表示字符串第 i 到 j 是否是回文。

边界:字符串长度为1 是为 TRUE

最优子结构(假设flag[i][j]表示字符串i到j的最长回文串):flag[i][j] = max{flag[i+1][j-1],j-i}

状态转换:

flag[i][i] = true flag[i][j] = max{flag[i+1][j-1],j-i}

由于判断flag[i][j]时,要保证 flag[i+1][j-1]已经判断,所以需要采用i降序和j升序的方式遍历

二、代码

public class Test {
    public static void main(String[] args) {
        String s = "babad";
        String palindrome = longestPalindrome(s);
        System.out.println(palindrome);
    }

    private static String longestPalindrome(String s) {
        if (s.isEmpty()) {
            return s;
        }
        int length = s.length();
        //表示字符串的左右下标
        int left = 0, right = 0;
        //初始二维数组flag[i][j],表示字符串第i到第j是否为回文
        boolean[][] flag = new boolean[length][length];
        for (int i = length - 2; i >= 0; i--) {
            flag[i][i] = true;
            for (int j = i + 1; j < length; j++) {
                //当字符串i所在的字符等于j所在的字符时,同时内部字符串flag[i+1][j-1]也为回文,则字符串i到j 为 TRUE
                //(j-i<3) 表示aba一定是回文
                flag[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 3 || flag[i + 1][j - 1]);
                //寻找最长回文串
                if (flag[i][j] && right - left < j - i) {
                    left = i;
                    right = j;
                }
            }
        }
        return s.substring(left,right+1);
    }
}

三、总结

  1. 动态规划需要好好理解:边界,最优子结构,状态转移
  2. 取出字符串的第i个字符:s.charAt(i)
  3. 截取长度为(right-left)的字符串:s.substring(left,right+1)