携手创作,共同成长!这是我参与「掘金日新计划 · 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;
画图表示
代码实现
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);
}