题目描述
https://leetcode-cn.com/problems/longest-palindromic-substring/
解法(存在的问题——dp数组遍历的顺序还不太明确)
第一次通过代码:
class Solution {
public String longestPalindrome(String s) {
//字符串,使用双指针,则使用二维数组
if(s==null) return null;
if(s.length()==0) return null;
if(s.length()==1) return s;
int[][]dp = new int[s.length()][s.length()];
//边界初始化
for(int i=0;i<s.length();i++){
for(int j=0;j<s.length();j++){
if(i>j)
dp[i][j] = 0;
else if(i==j)
dp[i][j] = 1;
}
}
int max = 0;
//递推
for(int i=s.length()-1;i>=0;i--){
for(int j=s.length()-1;j>=0;j--){
if(i<j){
if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){
dp[i][j] = j-i+1;//当前的字符串就是一个回文串
}else
dp[i][j] = Math.max(
dp[i+1][j],Math.max(1,//注意,可能是1最大了
dp[i][j-1])
);
}
if(max<dp[i][j]){
max = dp[i][j];
}
}
}
if(max==1) return s.substring(0,1);
// System.out.println(dp[0][s.length()-1]+" "+max);
//在dp数组里面找到和dp[0][s.length()-1]相等的值,那么它就是此时的最长回文字串
for(int i=0;i<s.length();i++){
for(int j=0;j<s.length();j++){
if(i<j && dp[i][j]==j-i+1 && dp[i][j]==max){//必须是该字串
//System.out.println(dp[0][s.length()-1]+" "+max+" "+i+" "+j);
return s.substring(i,j+1);
}
}
}//找不到,则不存在
return null;
}
}
第二次:
class Solution {
public String longestPalindrome(String s) {
//字符串,使用双指针,则使用二维数组
if(s==null) return null;
if(s.length()==0) return null;
if(s.length()==1) return s;
int[][]dp = new int[s.length()][s.length()];
//边界初始化
int max = 0;
//递推
for(int i=s.length()-1;i>=0;i--){
for(int j=s.length()-1;j>=0;j--){
if(i>j)
dp[i][j] = 0;
else if(i==j){
dp[i][j] = 1;
}else{
if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){
dp[i][j] = j-i+1;//当前的字符串就是一个回文串
}else
dp[i][j] = Math.max(
dp[i+1][j],Math.max(1,//注意,可能是1最大了
dp[i][j-1])
);
}
if(max<dp[i][j]){
max = dp[i][j];
}
}
}
//if(max==1) return s.substring(0,1);
// System.out.println(dp[0][s.length()-1]+" "+max);
//在dp数组里面找到和dp[0][s.length()-1]相等的值,那么它就是此时的最长回文字串
for(int i=0;i<s.length();i++){
for(int j=0;j<s.length();j++){
if(i<=j && dp[i][j]==j-i+1 && dp[i][j]==max){//必须是该字串
//System.out.println(dp[0][s.length()-1]+" "+max+" "+i+" "+j);
return s.substring(i,j+1);
}
}
}//找不到,则不存在
return null;
}
}
第三次:
class Solution {
public String longestPalindrome(String s) {
//字符串,使用双指针,则使用二维数组
if(s==null) return null;
if(s.length()==0) return null;
if(s.length()==1) return s;
int[][]dp = new int[s.length()][s.length()];
//边界初始化
int max = 0;
int start=0,end=0;
//递推
for(int i=s.length()-1;i>=0;i--){
for(int j=s.length()-1;j>=0;j--){
if(i>j)
dp[i][j] = 0;
else if(i==j){
dp[i][j] = 1;
}else{
if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){
dp[i][j] = j-i+1;//当前的字符串就是一个回文串
if(dp[i][j]>max){
start = i;
end = j;
}
}else
dp[i][j] = Math.max(
dp[i+1][j],Math.max(1,//注意,可能是1最大了
dp[i][j-1])
);
}
if(max<dp[i][j]){
max = dp[i][j];
}
}
}
return s.substring(start,end+1);
}
}
第四次:
class Solution {
public String longestPalindrome(String s) {
//字符串,使用双指针,则使用二维数组
if(s==null) return null;
if(s.length()==0) return "";
if(s.length()==1) return s;
int[][]dp = new int[s.length()][s.length()];
//边界初始化
int max = 1;//最大值起码等于1
int start=0,end=0;
//递推
for(int i=s.length()-1;i>=0;i--){
for(int j=s.length()-1;j>=0;j--){
if(i>j)
dp[i][j] = 0;
else if(i==j){
dp[i][j] = 1;
}else{
if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){//之前的dp[i+1][j-1]本身就是回文串
dp[i][j] = j-i+1;//当前的字符串就是一个回文串,一定会有一个dp[i][j]会进到这里
if(dp[i][j]>max){//只要进到这里,整体是回文串
start = i;
end = j;
max = dp[i][j];
}
}else//这里因为i<j,所以i+1<=j,dp[i+1][j]>=1,所以我们去掉了比较1
dp[i][j] = dp[i+1][j]>dp[i][j-1]?dp[i+1][j]:dp[i][j-1];
}
}
}
return s.substring(start,end+1);
}
}
发现存在了一个问题:
代码测试通过,但是
dp数组不知道为什么,最后计算出来的结果dp[0][s.length()-1]有时候不等于max,明明我定义的dp[i][j]表示是s[i…j]的最长回文串啊。
最后我耗费了点时间在idea里面调试,发现了问题:
就是dp[i][j-1]还没有算出来的时候,我拿来递推dp[i][j],所以我的j维度的遍历方向错了,导致得到的dp[0][s.length()-1]不一定等于max。但是好奇为什么能通过测试。
修改后的代码:
class Solution {
public String longestPalindrome(String s) {
//字符串,使用双指针,则使用二维数组
if(s==null) return null;
if(s.length()==0) return "";
if(s.length()==1) return s;
int[][]dp = new int[s.length()][s.length()];//dp[i][j]定义为从s[i..j]的最长回文串
//边界初始化
int max = 1;//最大值起码等于1
int start=0,end=0;
//递推
for(int i=s.length()-1;i>=0;i--){//从图上可视化看出应该使用后序遍历
for(int j=0;j<s.length();j++){
if(i>j)
dp[i][j] = 0;
else if(i==j){
dp[i][j] = 1;
}else{
if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){//之前的dp[i+1][j-1]本身就是回文串
dp[i][j] = j-i+1;//当前的字符串就是一个回文串,一定会有一个dp[i][j]会进到这里
if(dp[i][j]>max){//只要进到这里,整体是回文串
start = i;
end = j;
max = dp[i][j];
}
}else//这里因为i<j,所以i+1<=j,dp[i+1][j]>=1,所以我们去掉了比较1
dp[i][j] = dp[i+1][j]>dp[i][j-1]?dp[i+1][j]:dp[i][j-1];
}
}
}
//按理来说dp[0][s.length()-1]表示的是最大值,应该=max
return s.substring(start,end+1);
}
}