给你一个字符串s
,找到 s
中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
class Solution {
public:
void searchPalindrome(string s, int priorIndex, int nextIndex, int &maxLen, int &start) {
int step = 0;
while (priorIndex - step - 1 >= 0 && nextIndex + step + 1 <= s.size()) {
if (s[priorIndex - step - 1] != s[nextIndex + step + 1]) break;
else ++step;
}
int width = nextIndex - priorIndex + 1 + 2 * step;
if (maxLen < width) {
maxLen = width;
start = priorIndex - step;
}
}
string longestPalindrome(string s) {
if (s.size() <= 1) return s;
int pirorIndex = 0, nextIndex = 0;
int start = 0, maxLen = 0;
for (int i = 0; i < s.size() - 1; ++i) {
if (s[i] == s[i + 1]) {
pirorIndex = i;
nextIndex = i + 1;
searchPalindrome(s, pirorIndex, nextIndex, maxLen, start);
}
pirorIndex = i;
nextIndex = i;
searchPalindrome(s, pirorIndex, nextIndex, maxLen, start);
}
return s.substr(start, maxLen);
}
};
(其实,上面的方法就是中心扩展算法,只不过写法不一样!:))
思路二的思想是:可以从边界开始扩展,同样也可以找到正确的答案。
如果,从边界开始扩展,就需要分为两种情况:
- 奇数扩展:通俗来讲,就是从一个字符开始扩展
- 偶数扩展:从两个字符开始扩展
class Solution {
public:
pair<int, int> expandAroundCenter(const string &s, int left, int right) {
while (left >= 0 && right < s.size() && s[left] == s[right]) {
--left;
++right;
}
return {left + 1, right - 1};
}
string longestPalindrome(string s) {
if (s.size() <= 1) return s;
int start = 0, end = 0;
for (int i = 0; i < s.size(); ++i) {
auto [left1, right1] = expandAroundCenter(s, i, i + 1);
auto [left2, right2] = expandAroundCenter(s, i, i);
if (right1 - left1 > end - start) {
start = left1;
end = right1;
}
if (right2 - left2 > end - start) {
start = left2;
end = right2;
}
}
return s.substr(start, end - start + 1);
}
};
几个需要注意的边界问题:
- 主函数的
for
循环:这里的for
循环是遍历s
所有char
,所以取s.size()
- 为什么
return { left + 1, right - 1 }
?注意:while循环是先判断是否符合条件,所以,如果不符合条件的情况下,--left, ++right
是在上一次循环执行之后才不满足,所以要恢复符合情况下的left, right
LeetCode 5.最长回文子串