题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
求解思路1
类似动态规划的思想。从前往后遍历,maxs[i]储存包含s中第i个字符的最长回文子串,最后输出maxs中最长的。
示例:s = “babad”
i | maxs |
0 | b |
1 | a |
2 | bab |
3 | aba |
4 | d |
这应该算是暴力求解了,效率太低了!
代码1
执行用时:517 ms, 在所有 Java 提交中击败了8.44%的用户
内存消耗:39.2 MB, 在所有 Java 提交中击败了51.47%的用户
class Solution {
public String longestPalindrome(String s) {
if(s.length()==1){
return s;
}
List<String> maxs = new ArrayList<>(); //maxs[i]储存包含字符i的最长回文子串
maxs.add(""+s.charAt(0));
for(int i=1;i<s.length();i++){
int j=0;
for(;j<i;j++){ //从前往后遍历,看是否能构成回文子串
if(s.charAt(j)==s.charAt(i)){
int p = i;
int q = j;
while((s.charAt(p)==s.charAt(q))&&(p>q)){
p--;
q++;
if(p<=q){
break;
}
}
if(p<=q){
break;
}
}
}
maxs.add(s.substring(j,i+1));
}
int maxlen = maxs.get(0).length();
int maxi = 0;
for(int i=1;i<s.length();i++){ //找到最长的那个
if(maxs.get(i).length()>maxlen){
maxlen = maxs.get(i).length();
maxi = i;
}
}
return maxs.get(maxi);
}
}
其他解法:
二维数组动态规划实现:
用dp[i][j]标识字符串s从i到j是不是一个回文子串(1表示是,0表示不是)
当dp[i+1][j-1]=1,且s[i]=s[j]时,dp[i][j]=1;否则,dp[i][j]=0
注意:由于需要i+1的数据,所以i要从后往前遍历
代码如下:(但效率并没有提高很多呢)
执行用时:301 ms, 在所有 Java 提交中击败了33.51%的用户
内存消耗:49.5 MB, 在所有 Java 提交中击败了4.98%的用户
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if(len==1){
return s;
}
int[][] dp = new int[len][len];
for(int i=0;i<len;i++){
dp[i][i] = 1; //1:i到i能构成回文子串 0:不能构成回文字串
}
int maxlen = 1;
int mini = 0;
int maxj = 0;
for(int i=len-2;i>=0;i--){ //从i=len-2开始遍历
for(int j=i+1;j<len;j++){
if(i+1<=j-1){
if(s.charAt(i)==s.charAt(j)&&dp[i+1][j-1]==1){
dp[i][j] = 1;
if(j-i+1>maxlen){
maxlen = j-i+1;
mini = i;
maxj = j;
}
}else{
dp[i][j] = 0;
}
}
if(i+1==j){ //子串只有两个字母时
if(s.charAt(i)==s.charAt(j)){
dp[i][j] = 1;
if(j-i+1>maxlen){
maxlen = j-i+1;
mini = i;
maxj = j;
}
}
else{
dp[i][j] = 0;
}
}
}
}
return s.substring(mini,maxj+1);
}
}
一个月后(c++实现)
过了一个月再做,没做出来,马拉车算法也没看懂,实现了一下中心扩展法(按奇偶情况讨论),没想到还挺快的,在领扣中打败了97.6%
class Solution {
public:
/**
* @param s: input string
* @return: a string as the longest palindromic substring
*/
string longestPalindrome(string &s) {
int len = s.size();
int max=1;
int maxi=0;
//奇数
for(int i=0;i<len;i++){
int j = i-1;
int k = i+1;
while(j>=0&&k<len&&s[j]==s[k]){
j--;
k++;
}
if(k-j-1>max){
max = k-j-1;
maxi = j+1;
}
}
//偶数
for(int i=0;i<len;i++){
int j = i-1;
int k = i;
while(j>=0&&k<len&&s[j]==s[k]){
j--;
k++;
}
if(k-j-1>max){
max = k-j-1;
maxi = j+1;
}
}
return s.substr(maxi,max);
}
};