[Leetcode]5. 最长回文子串
题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
- 示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
- 示例 2:
输入:s = "cbbd"
输出:"bb"
- 示例 3:
输入:s = "a"
输出:"a"
- 示例 4:
输入:s = "ac"
输出:"a"
第一种解法(暴力解法)
class Solution {
//查询指定字符串最长子串
public String longestPalindrome(String s) {
int maxLen = 0;
int left = 0;
//babad
for (int i = 0; i < s.length(); i++) {
for (int j = i; j < s.length(); j++) {
String temp = s.substring(i, j + 1);
if ((j - i + 1) > maxLen && isPalindrome(temp)) {
maxLen = j - i + 1;
left = i;
}
}
}
return s.substring(left, maxLen + left);
}
private boolean isPalindrome(String source) {
char[] array = source.toCharArray();
int left = 0;
int right = array.length - 1;
while (left < right) {
if (array[left] != array[right]) {
return false;
}
left++;
right--;
}
return true;
}
public static void main(String[] args) {
System.out.println(new Solution().longestPalindrome("a"));
}
}
找出所有子串,判断每一个子串是否是回文串。时间复杂度为 O(N^3),超出时间限制。
第二种解法(中心扩展)
class Solution2 {
//查询指定字符串最长子串
public String longestPalindrome(String s) {
//babad
int[] res = new int[2];
for (int i = 0; i < s.length(); i++) {
searchPalindrome(s, i, i, res);
searchPalindrome(s, i, i + 1, res);
}
return s.substring(res[0], res[0] + res[1]);
}
private void searchPalindrome(String s, int start, int end, int[] res) {
while (start >= 0 && end < s.length()) {
if (s.charAt(start) != s.charAt(end)) {
break;
}
start--;
end++;
}
if (end - start - 1 > res[1]) {
res[0] = start + 1;
res[1] = end - start - 1;
}
}
public static void main(String[] args) {
System.out.println(new Solution2().longestPalindrome("a"));
}
}
从一个中心向两边扩展,直到可以判断出不是回文串,例如 habcdcbag ,以d为中心扩展,得到的回文串为 abcdcba,从所有回文串中选出最大的。时间复杂度为 O(N^2),可以通过AC。
第三种解法(动态规划)
class Solution3 {
//查询指定字符串最长子串
public String longestPalindrome(String s) {
int len = s.length();
if (len < 2) {
return s;
}
int maxLen = 1;
int start = 0;
//memo[j][i]表示下标j-i之间为回文串
boolean[][] memo = new boolean[len][len];
for (int i = 0; i < len; i++) {
memo[i][i] = true;
}
for (int i = 0; i < len; i++) {
for (int j = 0; j < i; j++) {
if (s.charAt(i) != s.charAt(j)) {
memo[j][i] = false;
} else {
//[0,2]
if (i - j < 3) {
memo[j][i] = true;
} else {
memo[j][i] = memo[j + 1][i - 1];
}
}
if (memo[j][i] && i - j + 1 > maxLen) {
maxLen = i - j + 1;
start = j;
}
}
}
return s.substring(start, start + maxLen);
}
public static void main(String[] args) {
System.out.println(new Solution3().longestPalindrome("abcbads"));
}
}
如果一个子串的头尾不相同,一定不是回文串,
如果相等,判断去除头尾之后的子串是否为回文串。
以 habcdcbag 字符串为例,habcdcba 不是回文子串,abcdcba 是回文子串。时间复杂度为 O(N^2),可以通过AC。