力扣刷题笔记《动态规划篇》→ 5. 最长回文子串

193 阅读1分钟

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

题目

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

示例

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

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

输入: s = "a"
输出: "a"

输入: s = "ac"
输出: "a"

提示

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母(大写和/或小写)组成

解题思路

针对子串问题,一般都可以通过 n - 1 来推导出 n 的值,在本题中,我们也可以通过同样的思路来进行推导。

  • 定义好数组 dp[n][n],初始化每位元素初始值为 true (单个字符串回文也是自身)_{(单个字符串回文也是自身)}
  • 由小区间往大区间拓展 (2,3,...,n)_{(2, 3, ..., n)} , 便于后续推导
  • 判断当前区间首尾两元素是否相同
  • 更新结果,截取子字符串返回

5.最长回文子串.gif

代码实现

class Solution {
    public String longestPalindrome(String s) {
        char[] c = s.toCharArray();
        int n = c.length;
        int maxLen = 1;
        int begin = 0;
        
        boolean[][] dp = new boolean[n][n];
        // 初始化每位元素
        for(int i = 0; i < n; ++i){
            dp[i][i] = true;
        }

        // 从长度为2开始,逐渐扩展
        for(int i = 2; i <= n; ++i){
            int k;
            // 向后推导当前长度下,改区间是否为回文串
            for(int j = 0; j < n; ++j){
                k = i + j - 1;
                if(k >= n){
                    break;
                }
                // 首尾两元素不相同则当前区间不为回文串
                if(c[j] != c[k]){
                    dp[j][k] = false;
                // 首尾两元素相同,且区间长度小于3则必定为回文串
                }else if(k - j < 3){
                    dp[j][k] = true;
                    // 根据子区间得到当前区间的状态
                }else{
                    dp[j][k] = dp[j + 1][k - 1];
                }
                // 更新结果
                if(dp[j][k] && k - j + 1 > maxLen){
                    maxLen = k - j + 1;
                    begin = j;
                }
            }
        }
        // 返回结果
        return s.substring(begin, begin + maxLen);
    }
}

复杂度分析

  • 时间复杂度:O(NN)
  • 空间复杂度:O(NN)

最后

文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!

如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!

题目出处: leetcode-cn.com/problems/lo…