5. 最长回文子串 + 动态规划
5. 最长回文子串
LeetCode_5
题目详情
方法一:暴力法(超时)
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
int maxLen = 0;
String result = "";
for(int i=0; i<len; i++){
for(int j=len-1; j>=i; j--){
int k=i,l=j;
while(k<=l && s.charAt(k) == s.charAt(l)){
k++;l--;
}
if(k>=l && j-i+1 >= maxLen){
maxLen = Math.max(maxLen, j-i+1);
result = s.substring(i, j+1);
}
}
}
return result;
}
}
方法二:动态规划法
- 对于一个子串而言,如果它是回文串,并且长度大于 22,那么将它首尾的两个字母去除之后,它仍然是个回文串。例如对于字符串 “ababa”,如果我们已经知道 “bab” 是回文串,那么 “ababa” 一定是回文串,这是因为它的首尾两个字母都是 “a”。
- 也就是说,只有 s[i+1:j−1] 是回文串,并且 s 的第 i 和 j 个字母相同时,s[i:j] 才会是回文串。
- 在状态转移方程中,我们是从长度较短的字符串向长度较长的字符串进行转移的,因此一定要注意动态规划的循环顺序。
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
boolean[][] dp = new boolean[len][len];
String result = "";
for(int l=0; l<len; l++){//l表示子串的长度,子串的长度从小到大
for(int i=0; i+l<len; i++){//i表示子串的起始位置
int j = i+l;
if(l==0)
dp[i][j] = true;
else if(l==1)
dp[i][j] = s.charAt(i) == s.charAt(j);
else
dp[i][j] = (s.charAt(i) == s.charAt(j)) && dp[i+1][j-1];
if(dp[i][j] && l+1 >= result.length()){
result = s.substring(i, j+1);
}
}
}
return result;
}
}
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
// dp[i][j]表示(i, j)的子串是否是回文子串
boolean[][] dp = new boolean[n][n];
// dp[i][j] = dp[i+1][j-1];
String res = "" + s.charAt(0);
for(int i=0; i<n; i++){
dp[i][i] = true;
}
for(int i=n-1; i>=0; i--){
for(int j=i+1; j<n; j++){
if(i + 1 == j){
dp[i][j] = s.charAt(i) == s.charAt(j);
}else{
dp[i][j] = s.charAt(i) == s.charAt(j) && dp[i+1][j-1];
}
if(dp[i][j] && j-i+1 > res.length()){
res = s.substring(i, j+1);
}
}
}
return res;
}
}
Either Excellent or Rusty