一、题解
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例1:
输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。
示例2:
输入: "cbbd" 输出: "bb"
暴力解法,会超时,需要考虑动态规划,
动态规划参考:什么是动态规划
思路就是创建一个二维数组,boolean[][] flag, flag[i][j] 表示字符串第 i 到 j 是否是回文。
边界:字符串长度为1 是为 TRUE
最优子结构(假设flag[i][j]表示字符串i到j的最长回文串):flag[i][j] = max{flag[i+1][j-1],j-i}
状态转换:
flag[i][i] = trueflag[i][j] = max{flag[i+1][j-1],j-i}
由于判断flag[i][j]时,要保证 flag[i+1][j-1]已经判断,所以需要采用i降序和j升序的方式遍历
二、代码
public class Test {
public static void main(String[] args) {
String s = "babad";
String palindrome = longestPalindrome(s);
System.out.println(palindrome);
}
private static String longestPalindrome(String s) {
if (s.isEmpty()) {
return s;
}
int length = s.length();
//表示字符串的左右下标
int left = 0, right = 0;
//初始二维数组flag[i][j],表示字符串第i到第j是否为回文
boolean[][] flag = new boolean[length][length];
for (int i = length - 2; i >= 0; i--) {
flag[i][i] = true;
for (int j = i + 1; j < length; j++) {
//当字符串i所在的字符等于j所在的字符时,同时内部字符串flag[i+1][j-1]也为回文,则字符串i到j 为 TRUE
//(j-i<3) 表示aba一定是回文
flag[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 3 || flag[i + 1][j - 1]);
//寻找最长回文串
if (flag[i][j] && right - left < j - i) {
left = i;
right = j;
}
}
}
return s.substring(left,right+1);
}
}
三、总结
- 动态规划需要好好理解:边界,最优子结构,状态转移
- 取出字符串的第i个字符:
s.charAt(i) - 截取长度为(
right-left)的字符串:s.substring(left,right+1)