Leetcode5. 最长回文子串
因为队友原因,自己退出了ICPC小组,Codeforces可能不打下去了,从今天开始更新Leetcode题目(1天5题左右)。(5天连一道题目都不补的纯➗生)
首先我点开非常重要的动态规划,DP一共454题,准备一天5题按顺序做完。
使用的语言均为Java。
5.最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
题意非常明显,让我们找到最长回文子串。我们有多种思路来解决这个问题。
1.DP:设dp[i][j]为从s[i]到s[j](其中s[i]………s[j]为回文子串需要判断,所以将dp这个二维数组设置为boolean类型) 首先我们需要特判:s.length()<2时,return s即可;其余情况,我们就需要一个maxLen变量,来更新答案。首先声明一个数组,并声明一个char数组来遍历字符串s:
int len=s.length(); if(len<2) return s; int maxLen=1; int begin=0; // dp[i][j]表示s[i..j] 是否是回文串 boolean [][] dp=new boolean[len][len]; for(int i=0;i<len;i++){ dp[i][i]=true; } char []charArray=s.toCharArray();
然后,枚举左边界求出右边界,j-i+1=L,枚举L和i,那么j=L+i-1;转移状态方程也很好想:dp[i][j]=true(s[i]………s[j]为回文子串) dp[i][j]=false(其中s[i]………s[j]不为回文子串)
但是在false处有两种情况,一种是i>j明显不符合左右边界的特点(左边界一定在右边界左边);还有一种是s[i]………s[j]不为回文子串。
可以写出状态转移方程:
for(int L=1;L<=len;L++){ for(int i=0;i<len;i++){ int j=L+i-1; if(j>=len) break; if(charArray[i]!=charArray[j]){ dp[i][j]=false; } else{ if(j-i<3) dp[i][j]=true; else dp[i][j]=dp[i+1][j-1]; }
然后处理完就需要更新maxLen了,当dp[i][j]==true&&j-i+1>maxLen时,我们就更新maxLen即可。
if(dp[i][j]&&j-i+1>maxLen){ maxLen=j-i+1; begin=i; }
最后调库输出substring即可。
最终代码:
class Solution { public String longestPalindrome(String s) { int maxLen=1; int len=s.length(); int begin=0; if(len<2) return s; boolean [][]dp=new boolean[len][len]; for(int i=0;i<len;i++){ dp[i][i]=true; } char []charArray=s.toCharArray(); for(int L=1;L<=len;L++){ for(int i=0;i<len;i++){ int j=L+i-1; if(j>=len) break; if(charArray[i]!=charArray[j]){ dp[i][j]=false; } else{ if(j-i<3) dp[i][j]=true; else{ dp[i][j]=dp[i+1][j-1];//two pointers } } if(dp[i][j]&&j-i+1>maxLen){ maxLen=j-i+1; begin=i; } } } return s.substring(begin,begin+maxLen); } }
2.中心扩散法:
从中间向两边扩散开,实际上运用的是双指针思想,写一个expand函数,当left左指针>=0&&right右指针<s.length()&&s.charAt(left)==s.charAt(right)时,左指针left++,右指针right--;然后设置两个变量start和end,通过遍历求出max(expand(s,i,i),expand(s,i,i+1)),更新start和end,最后输出子串即可。
class Solution { public String longestPalindrome(String s) { if(s==null||s.length()<1) return ""; int start=0; int end=0; int len=s.length(); for(int i=0;i<len;i++){ int len1=expand(s,i,i); int len2=expand(s,i,i+1); int lenMax=Math.max(len1,len2); if(lenMax>end-start){ start=i-(lenMax-1)/2; end=i+lenMax/2; } } return s.substring(start,end+1); } public int expand(String s,int left,int right) { while(left>=0&&right<s.length()&&s.charAt(left)==s.charAt(right)) { --left; ++right; } return right-left-1; } }

浙公网安备 33010602011771号