1.题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2.我的题解
2.1 暴力法
- 时间复杂度:
O(n^3)
; - 空间复杂度::
O(1)
,常数个变量;
class Solution {
bool isPalindrom(string s,int l,int r){
if(s.empty())return false;
int i=l,j=r;
while(i<j){
if(s[i++]!=s[j--])return false;
}
return true;
}
public:
string longestPalindrome(string s) {
string res="";
int len=0;
for(int i=0;i<s.size();i++){
for(int j=i;j<s.size();j++){
if(isPalindrom(s,i,j)==false)continue;
if(j-i+1<=len)continue;
len=j-i+1;
res=s.substr(i,len);
}
}
return res;
}
};
3.别人的题解
3.1 中心扩展算法
- 从每一个位置开始,向左右扩展找最长回文子串;
- 共有
n+(n-1)
个位置,分子串长度奇偶讨论。奇数长度由n
个位置向外扩展,偶数长度由n-1
个位置(原数组的空隙)向外扩展。
class Solution {
int extend(string &s,int mid){
int l=0;
while(mid-l>=0 && mid+l<s.size() &&s[mid-l]==s[mid+l]){
++l;
}
return l-1;
}
int extend(string &s,int midL,int midR){
int l=0;
while(midL-l>=0 && midR+l<s.size() && s[midL-l]==s[midR+l]){
++l;
}
return l-1;
}
public:
string longestPalindrome(string s) {
string res="";
int len=-1;
for(int i=0;i<s.size();i++){
int l = extend(s,i);
if(l>=0 && (l<<1)+1>len){
len=(l<<1)+1;
res = s.substr(i-l,len);
}
if(i<s.size()-1){
l=extend(s,i,i+1);
if(l>=0 && (l<<1)+2>len){
len=(l<<1)+2;
res = s.substr(i-l,len);
}
}
}
return res;
}
};
优雅一点的写法:
class Solution {
int extend(string &s,int l,int r){
while(l>=0 && r<s.size() && s[l]==s[r]){
--l;
++r;
}
return r-l-1;
}
public:
string longestPalindrome(string s) {
int start=0,end=0;
for(int i=0;i<s.size();i++){
int len1=extend(s,i,i);
int len2=extend(s,i,i+1);
len1=max(len1,len2);
if(len1>end-start){
start=i-(len1-1)/2;
end=i+len1/2;
}
}
return s.substr(start,end-start+1);
}
};
4.总结与反思
(1)最长回文子串的判定:
- 中心扩展定理;