题意描述:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例:
示例一:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例二:
输入: "cbbd"
输出: "bb"
解题思路:
Alice: 我用 Python 实现的暴力算法居然超时了。 hhh(’∇’)シ┳━┳
Bob: 再用 C++ 或者 Java 试一试,说不定能过。
Alice; 还有别的方法吗 ? 这题有点像动态规划呀,我都能找到递推公式对应的关系了。如果子串 s[i][j]
是回文的而且 s[i-1] == s[j + 1]
那么 s[i-1][j+1]
也是回文的。
Bob: 不错不错,还有一个问题,如果最长的回文字符串长度是偶数怎么办 ?
Alice: 偶数也可以处理啊,只要保证 在计算 dp[i-1][j+1]
的时候已经计算出 dp[i][j]
的值就好了。
Bob: 那这样的话,我们在初始化的时候要做两次,一次是长度是 1 的子串,一次是长度是 2 的子串。这样算长度为 3 的回文子串的时候用到 第一次初始化的值,计算长度为 4 的回文子串的时候用到 第二次初始化的值。然后一直这样算下去…
Alice: 对,就是这样,很典型的一个 二维动态规划的问题嘛。
Bob: hhh😎
代码:
Python 方法一:双重循环暴力求解。
class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s) <= 1:
return s
# 处理边界值条件
ans = 1
ret = s[0]
# 双重循环,遍历所有可能的子串
for x in range(0, len(s)):
for y in range(x+1, len(s)):
if self.isPalindrome(s[x:y+1]):
if y - x + 1 > ans:
ans = y - x + 1
ret = s[x:y+1]
return ret
def isPalindrome(self, s: str) -> bool:
# 判断一个字符串是不是回文字符串
return s[::-1] == s
Java 方法一: 双重循环暴力求解。
class Solution {
public String longestPalindrome(String s) {
if(s.length() <= 1){
return s;
}else{
int maxLength = 1;
String answer = "" + s.charAt(0);
for(int i=0; i<s.length(); ++i){
for(int j=i+1; j<s.length(); ++j){
if(j-i+1 > maxLength){
if(isPalindrome(s.substring(i, j+1))){
maxLength = j-i+1;
answer = s.substring(i, j+1);
}
}
}
}
return answer;
}
}
public boolean isPalindrome(String s){
for(int i=0; i<s.length()/2; ++i){
if(s.charAt(i) != s.charAt(s.length()-1-i)){
return false;
}
}
return true;
}
}
Python方法二: 二维 动态规划,通过。😎
class Solution:
def longestPalindrome(self, s: str) -> str:
if len(s) < 2:
return s
# initiation
maxValue = 0
left = 0
right = 0
dp = [[0 for x in range(len(s))] for z in range(len(s))]
#dp[i][j] == 1 即数组中下标为 i,j 的子串是回文子串
for x in range(len(s)-1):
dp[x][x] = 1
if s[x] == s[x+1]:
dp[x][x+1] = 1
maxValue = 2
left = x
right = x + 1
dp[len(s)-1][len(s)-1] = 1
for strlen in range(3, len(s) + 1):
for l in range(0, len(s)-strlen+1):
if s[l] == s[l + strlen - 1] and dp[l+1][l + strlen - 2] == 1:
dp[l][l + strlen - 1] = 1
if dp[l][l + strlen - 1] == 1 and strlen > maxValue:
maxValue = strlen
left = l
right = l + strlen - 1
#print(left, right, maxValue)
#print(left, right)
return s[left:right+1]
Java 方法二: 动态规划。
class Solution {
public String longestPalindrome(String s) {
if(s.length() < 2){
return s;
}else{
int[][] dp = new int[s.length()][s.length()];
int maxValue = 0;
int left = 0;
int right = 0;
for(int i=0; i<s.length()-1; ++i){
dp[i][i] = 1;
if(s.charAt(i) == s.charAt(i + 1)){
dp[i][i+1] = 1;
maxValue = 2;
left = i;
right = i + 1;
}
}
for(int len=3; len<=s.length(); ++len){
for(int l=0; l<=s.length()-len; ++l){
if(s.charAt(l) == s.charAt(l+len-1) && dp[l+1][l+len-2] == 1){
dp[l][l+len-1] = 1;
if(len > maxValue){
maxValue = len;
left = l;
right = l+len-1;
}
}
}
}
return s.substring(left, right+1);
}
}
}
易错点:
- 一些测试样例:
"ababa"
"abcda"
"aaaaaaaaaaaaaaaaaaaaaaaaaa"
"dsdsdfsdf"
"ab"
"aa"
"a"
""
- 答案:
"ababa"
"a"
"aaaaaaaaaaaaaaaaaaaaaaaaaa"
"dsdsd"
"a"
"aa"
"a"
""
总结: