题目描述:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:
输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案。
示例 2:
输入: "cbbd" 输出: "bb"
解题思路:
简单直观的解法,回文是中心对称的,所以从第二个字符开始,判断是否是中心对称。
执行用时:12 ms, 在所有 C++ 提交中击败了95.47%的用户
内存消耗:7 MB, 在所有 C++ 提交中击败了89.26%的用户
C++代码:
class Solution {
public:
string longestPalindrome(string s) {
// 找到回文开始的索引start,和回文的长度max_len.
int s_len = s.size();
int start_idx = 0; // 最长回文开始的索引start
int max_len = 0; // 最长回文长度。
// 1. 如果长度小于等于1,则字符串本身
if (s_len <= 1) return s;
// 2. 因为回文是对称的,从第二项开始,判断左右是否对称
// 以i-1和i为中心的偶数长度回文,或者以i为z中中心的奇数长度回文
for (int i = 1; i < s_len; i++)
{
// 3. 找是否有偶数长度的回文,向两边扩展,找到最左边索引low和最右边索引high
int low = i-1, high=i; // 初始时回文左右两边索引是i-1和i. abb
while (0 <= low && high < s_len && s[low] == s[high]) // 左右不越界,并且字符相等
{
low--;
high++; // 符合以上两个条件,则更新回文的左右索引
}
// 找到后更新start_idx和max_len
low++; //上面多移动了一位
high--;
if (high - low + 1 > max_len)
{
start_idx = low;
max_len = high - low + 1;
}
// 找是否有奇数长度的回文,向两边扩展,找到最左边索引low和最右边索引high
low = i-1, high = i+1; // 回文中间索引是i,初始时两边索引是i-1和i+1. aba
while (0 <= low && high <= s_len && s[low] == s[high])
{
low--;
high++;
}
// 找到后更新start_idx和max_len
low++;
high--;
if (high - low + 1 > max_len)
{
start_idx = low;
max_len = high - low + 1;
}
}
return s.substr(start_idx, max_len);
}
};
简化版:
class Solution {
public:
string longestPalindrome(string s) {
// 回文是中心对称的
if (s.size() <= 1) return s;
int max_len = 0;
int start_idx = 0;
for (int i = 1; i < s.size(); i++) // 以i-1和i为中心的偶数长度回文,或者以i为z中中心的奇数长度回文
{
// 查看是否有偶数长度的回文,有则会更新max_len和start_idx
int low = i - 1, high = i; // 如果是偶数,中心对称,往两边扩展. abb
huiwen_idx(s, low, high, max_len, start_idx);
// 查看是否有奇数长度回文,有则会更新max_len和start_idx
low = i-1; high = i+1;
huiwen_idx(s, low, high, max_len, start_idx);
}
return s.substr(start_idx, max_len);
}
void huiwen_idx(string s, int low, int high, int &max_len, int &start_idx)
{
while (0 <= low && high < s.size() && s[low] == s[high])
{
low--;
high++;
}
low++;
high--;
// 确认是否需要更新
if (max_len < (high-low+1))
{
max_len = high - low + 1;
start_idx = low;
}
}
};
对应的Python解法
python代码:
执行用时:444 ms, 在所有 Python 提交中击败了94.00%的用户
内存消耗:13.1 MB, 在所有 Python 提交中击败了79.54%的用户
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
# 1, 长度为0或者1
s_len = len(s)
if s_len <= 1:
return s
# 获取最长回文开始的索引start_idx,和长度max_len
start_idx = 0
max_len = 0
for i in range(1, s_len):
# 2. 偶数回文中间位置是i-1, i
low = i-1
high = i
while 0 <= low and high < s_len and s[low] == s[high]:
low = low - 1
high = high + 1
low = low + 1 # 回到真实的回文左右索引
high = high -1
# 判断长度是否比之前记录的长
if high-low+1 > max_len:
start_idx = low
max_len = high - low + 1
# 3.奇数回文中间位置是i
low = i-1
high = i+1
while 0 <= low and high < s_len and s[low] == s[high]:
low = low - 1
high = high + 1
low = low + 1
high = high - 1
if high-low+1 > max_len:
start_idx = low
max_len = high - low + 1
return s[start_idx:start_idx+max_len]