给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad” 输出: “bab” 注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd” 输出: “bb”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
- 暴力法:从字符串两头遍历,只要两个字符相等,并且字符串长度大于当前最大回文字串长度值,即开始判断该子串是否为回文子串,如是,则更新该值。
class Solution {
public:
bool isRight(const string& s)
{
for(int i = 0;i < s.length()/2 ;i++)
{
if(s[i] != s[s.length()-1-i])
return false;
}
return true;
}
string longestPalindrome(string s) {
int maxLen = 0;
string ret;
for(int i = 0;i<s.length();i++)
{
for(int j = s.length()-1;j >= 0;j--)
{
if(s[i]==s[j] && (j-i+1 > maxLen) && isRight(s.substr(i,j-i+1)))
{
if(j-i+1 > maxLen)
{
maxLen = j-i+1;
ret = s.substr(i,j-i+1);
}
}
}
}
return ret;
}
};
可以看到上述耗时比较多,由于进行剪枝较多,后期执行时间较少,时间复杂度达到了
O
(
N
3
)
O(N^3)
O(N3)
- 中心扩散法,利用回文串的性质,如果当前子串是回文子串,那么扩展两边上的字符如果相同,那么就可以扩大范围了,如此循环,直到遇到边界。时间复杂度为 O ( N 2 ) O(N^2) O(N2),空间复杂度 O ( 1 ) O(1) O(1)
class Solution {
public:
pair<int, int> getMaxLen(const string& s,int left,int right)
{
while(left>=0 && right<s.length() && s[left] == s[right])
{
left--;
right++;
}
return {left+1,right-1};
}
string longestPalindrome(string s) {
if(s.length()==0 || s.length()==1)
{
return s;
}
int maxLen = 0;
string ret;
int left1,right1,left2,right2;
int start = 0,end = 0;
for(int i = 0;i<s.length();i++)
{
auto [left1,right1] = getMaxLen(s,i,i);
auto [left2,right2] = getMaxLen(s,i,i+1);
if(right1 - left1 > maxLen)
{
start = left1;
end = right1;
maxLen = right1 - left1;
}
if(right2 - left2 > maxLen)
{
start = left2;
end = right2;
maxLen = right2 - left2;
}
}
return s.substr(start,end-start+1);
}
};