力扣第五题-最长回文子串|Java 刷题打卡

681 阅读2分钟

本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接

前言

力扣第五题如下所示: 在这里插入图片描述

一、思路

首先要知道什么是回文子串,定义如下:
回文子串:正着念和反着念是一样的,例如abcdcba,正着念是abcdcba反着念也是abcdcba

从题目可以得知以下两个信息:

  • 输入:字符串
  • 输出:最长回文子串
  • 目标:找到这个字符串的所有的回文子串,只保留最长即可。

仔细看一下回文子串,你会发现回文子串左右添加同样的字符仍构成回文子串。例如:cdc左右都加上b为bcdcb仍是一个回文子串。

假设字符串数组为str,i和j表示下标

再将思路反过来,str[i] ~ str[j] 是不是回文子串有两种情况

  • str[i] != str[j]:不是回文子串
  • str[i] == str[j]:如果 str[i+1] ~ str[j-1] 是回文子串,则为回文子串

很明显,这一题就可以使用动态规划来解决了。可得到下面的状态转移方程:

dp[i][j]:表示 i ~ j 是不是回文子串 str[]:表示字符串数组

状态转移方程:dp[i][j] = dp[i+1][j-1] && str[i] == str[j]

二、实现

优化:因为回文子串是对称的,所以忽略左下角的元素

代码实现

    /**
     * 动态规划:最长回文子串
     * 以abcbd为例子
     *
     */
    public String longestPalindrome(String s) {
        // 特殊情况,直接返回
        if ("".equals(s)) {
            return null;
        }

        int[][] dp = new int[s.length()][s.length()];

        int begin = 0;  // 回文子串起始位置
        int maxLen = 1; // 子串的最大长度(最小值为1)

        // 开始填表格(从表格左上角开始),忽略对角线
        for (int j=0; j<s.length(); j++) {
            for (int i=0; i<=j; i++) {
                // 对角线
                if (i == j) {
                    dp[i][j] = 1;
                } else {
                    boolean b = s.charAt(i) == s.charAt(j);
                    // 相邻且相等
                    if (i+1==j && b) {
                        dp[i][j] = 1;
                    } else if (b && dp[i+1][j-1] == 1) {
                        dp[i][j] = 1;
                    }
                    // 因int数组默认值为0,可以省略此处的else

                    // 判断是否需要更新子串
                    if (dp[i][j] == 1 && j-i+1>maxLen){
                        maxLen=j-i+1;
                        begin=i;
                    }
                }
            }
        }
        return s.substring(begin, begin+maxLen);
    }

三、总结

今天是力扣第五题~
本系列将会更新力扣的1-10题,连续更新10天!
掘金币,我来啦😁