leetcode刷题日记-【5. 最长回文子串】

63 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

题目描述

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

 

示例 1:

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

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

提示:

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

题目要素

  • 给定字符串,只包含数字及字母。查找字符串中最大回文字符串。
  • 首先确定回文,回文是指正序和倒叙获取的字符串都是一样的,即字符串两头两位的字符依次相等。

这是个典型的动态规划问题,可以将大问题具体往下继续细分。

即i,j位置的字符串事否是回文字符串可以取决于i+1,j-1之间的字符串是否是回文字符串且i,j两个位置的字符必须相等。

写成表达式就是dp[i][j] = dp[i+1][j-1] && s[i]+s[j]; 其中dp[i][j]就是指i,j之间的值是否是回文字符串。 再来确定初始条件,单个字符肯定是回文,即dp[i][i] = true;

画图表示

image.png

代码实现

public String longestPalindrome(String s) {
    char[] chars = s.toCharArray();
    boolean[][] dp = new boolean[chars.length][chars.length];
    // 初始条件,dp[i][i]一定是true
    for (int i = 0;i < chars.length; i++){
        dp[i][i] = true;
    }
    // 最大回文长度,存储之后进行比较并设值
    int maxLength = 1;
    // 最大回文长度,左边界
    int beginIndex = 0;
    for (int L=2;L <= chars.length; L++) {
        //长度从2开始,因为长度为1的肯定是回文
        for (int i = 0 ; i < chars.length ; i++) {
            //左边界
            //计算右边界
            int j = i + L -1;
            // 如果j已经到了字符串底端,则直接进行下次循环
            if (j >= chars.length) {
                break;
            }
            // 对dp[i][j]进行赋值操作
            if (chars[i] == chars[j]) {
                // 字符串包含3个或2个字符,一定是回文
                if (j - i < 3) {
                    dp[i][j] = true;
                }else {
                    dp[i][j] = dp[i+1][j-1];
                }
            }
            if (dp[i][j] && L > maxLength){
                // 两个字符相等,则取决于两个边界向内收缩的字符串是否是回文
                maxLength = L;
                beginIndex = i;
            }
        }
    }
    return s.substring(beginIndex,beginIndex + maxLength);
}