解法 1: 暴力破解
暴力求解,列举所有的子串,判断是否为回文串,保存最长的回文串。
时间复杂度:两层 for 循环O(n²),for循环里边判断是否为回文O(n),所以时间复杂度为 O(n³)。超时。
空间复杂度:O(1),常数个变量。
class Solution {
private:
bool isPalindromic(string s) {
int len = s.size();
for (int i = 0; i < len / 2; i++) {
if (s[i] != s[len - i - 1]) {
return false;
}
}
return true;
}
public:
string longestPalindrome(string s) {
string ans = "";
int max = 0;
int len = s.size();
for (int i = 0; i < len; i++){
for (int j = i + 1; j <= len; j++) {
string test = s.substr(i, j);
if (isPalindromic(test) && test.size() > max) {
ans = s.substr(i, j);
max = max>ans.size()?max:ans.size();
}
}
}
return ans;
}
};
方法二:中心扩散法
class Solution {
public:
string longestPalindrome(string s) {
string res="";
int leng=0,start=0,end=0;
if(s.size()==0 || s.size()==1) return s;
for(int i=0;i<s.size();i++){
int len1=length(s,i,i); //奇数子串
int len2=length(s,i,i+1); //偶数子串
int len=max(len1,len2);
if(len>leng){
start=i-(len-1)/2; //计算起始点,奇偶都可以
end=i+len/2;
leng=end-start+1;
}
}
return s.substr(start,leng); //截取最长子串
}
private:
int length(string s,int l,int r){ //计算以l和r为中心的最长子串长度
while(l>=0 && r<s.size() && s[l]==s[r]){
r++;
l--;
}
return r-l-1;
}
};
方法三:动态规划
状态:dp[i][j]表示子字符串s[i,j]是否为回文子串,为闭区间。
状态转移方程:dp[i][j] = (s[i] == s[j]) && dp[i + 1][j - 1],其中dp[i + 1][j - 1] 要考虑边界情况
class Solution {
public:
string longestPalindrome(string s) {
int n=s.size();
if(n<2)
return s;
int begin=0,maxlen=1; //记录最长回文子串的开始地址和长度
vector<vector<bool>> dp(n,vector<bool>(n,false));
//初始化
for(int i=0;i<n;i++)
dp[i][i]=true;
//状态转移
for(int j=1;j<n;j++){
for(int i=0;i<j;i++){
if(s[i]!=s[j])
dp[i][j]=false;
else{
if(j-i<3)
dp[i][j]=true;
else
dp[i][j]=dp[i+1][j-1];
}
if(dp[i][j] && j-i+1>maxlen){
maxlen=j-i+1;
begin=i;
}
}
}
return s.substr(begin,maxlen);
}
};