题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
思路
这一题使用动态规划解决:
-
使用二维数组
dp[i][j]
来代表第i个字符和第j个字符是否一样,一样的话为true,如下图- 右下方没有是因为回文串是从前往后,所以没有
- 对角线肯定是为true,因为是自己与自己对比
- 00为true,01为false,02位true,03为false,04位true;依次这样对比
-
要想证明i和j中间的子串是回文子串,就必须要保证i和j中间的子串也是回文串,所以需要满足条件:
dp[i + 1][j - 1]
是true -
考虑头尾去掉以后没有字符剩余,或者剩下一个字符的时候,肯定是回文串;所以边界条件是
j - i < 3
-
由上综合可知是回文串:首先要保证
dp[i][j] = (s[i]==s[j]) and dp[i+1][j-1
是为true,其次是边界条件j - i < 3
代码
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
// 当小于2时,肯定是回文串
if (len < 2){
return s;
}
//最长子串长度
int maxLen = 1;
//开始的位置
int begin = 0;
// 1. 状态定义
// dp[i][j] 表示s[i...j] 是否是回文串
// 2. 初始化
boolean[][] dp = new boolean[len][len];
for (int i = 0; i < len; i++) {
dp[i][i] = true;
}
char[] chars = s.toCharArray();
// 3. 状态转移
// 注意:先填左下角
// 填表规则:先一列一列的填写,再一行一行的填,保证左下方的单元格先进行计算
for (int j = 1;j < len;j++){
for (int i = 0; i < j; i++) {
// 头尾字符不相等,不是回文串
if (chars[i] != chars[j]){
dp[i][j] = false;
}else {
// 相等的情况下
// 考虑头尾去掉以后没有字符剩余,或者剩下一个字符的时候,肯定是回文串
if (j - i < 3){
dp[i][j] = true;
}else {
// 状态转移
dp[i][j] = dp[i + 1][j - 1];
}
}
// 只要dp[i][j] == true 成立,表示s[i...j] 是否是回文串
// 此时更新记录回文长度和起始位置
if (dp[i][j] && j - i + 1 > maxLen){
maxLen = j - i + 1;
begin = i;
}
}
}
// 4. 返回值
return s.substring(begin,begin + maxLen);
}
}
代码说明
看注释,。。