题目描述
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
解题思路
利用回文字符串的特点:正着读和反着读都是一样的,所以首先把s反转,利用i和j控制左右边界,不断从s中截取子字符串,这时需要理解反转字符串中对应i和j的关系,同时从反转字符串中进行截取,进行比较。max表示当前字符串的长度,如果新的子字符串长度大于max才将替换。
public static String longestPalindrome(String s) {
int len = s.length();
String str = "";
String reverse = new StringBuffer(s).reverse().toString();
int max = -1;
if (len <= 1)
return s;
for (int i = 0; i < len; i++) {
for (int j = len; j > i; j--) {
String sub1 = s.substring(i, j);
String sub2 = reverse.substring(s.length() - j, reverse.length() - i);
if (sub2.equals(sub1)) {
if (j - i > max) {
str = sub1;
max = j - i;
}
}
}
}
return str;
}
本以为可以痛痛快快的通过测试,没想到居然超时了!!!!
现在对上面代码进行优化,优化1:因为j是从后向前循环的,所以当j-i>max时,替换当前str时,直接break,因为j是不断的变小,所以就算以后出现了回文字符串,也会比当前保存的回文字符串短。优化2:当len-i< max时,应该直接返回str,因为以后的子字符串长度必然没有str的长度长。
public static String longestPalindrome(String s) {
int len = s.length();
String str = "";
String reverse = new StringBuffer(s).reverse().toString();
int max = -1;
if (len <= 1)
return s;
for (int i = 0; i < len; i++) {
if (len - i < max)
return str;
for (int j = len; j > i; j--) {
String sub1 = s.substring(i, j);
String sub2 = reverse.substring(s.length() - j, reverse.length() - i);
if (sub2.equals(sub1)) {
if (j - i > max) {
str = sub1;
max = j - i;
break;
}
}
}
}
return str;
}
怀着忐忑的心情,再次测试用例,这次勉强通过了。看到执行结果看到速度还是可以的。
本题还有很多方法可以实现:暴力破解、动态规划,我这次采用的是较为简单的思路,希望有大佬可以指出还有什么优化方式。