给你一个字符串 s,找到 s 中最长的 回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母组成`
要找到字符串 s
中最长的回文子串,可以使用动态规划或中心扩展法。这里我们介绍中心扩展法,因为它更直观且易于理解。
中心扩展法思路:
- 回文中心:回文子串的中心可以是一个字符(如 “aba” 的中心是 ‘b’),也可以是两个字符(如 “abba” 的中心是 ‘bb’)。
- 扩展:对于每个可能的中心,向左右扩展,直到字符不匹配或到达字符串的边界。
- 记录最长回文子串:在扩展过程中,记录下最长的回文子串。
以下是 Python、Java 和 C++ 的实现代码,用于找到字符串 s
中最长的回文子串。
Python 实现
def longestPalindrome(s: str) -> str:
def expandAroundCenter(left: int, right: int) -> str:
# 从中心向左右扩展,找到最长的回文子串
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
# 返回当前最长的回文子串
return s[left + 1:right]
# 初始化最长回文子串为空
longest = ""
# 遍历每个字符,作为回文中心
for i in range(len(s)):
# 奇数长度的回文子串
palindrome1 = expandAroundCenter(i, i)
# 偶数长度的回文子串
palindrome2 = expandAroundCenter(i, i + 1)
# 更新最长回文子串
if len(palindrome1) > len(longest):
longest = palindrome1
if len(palindrome2) > len(longest):
longest = palindrome2
return longest
# 测试
print(longestPalindrome("babad")) # 输出: "bab" 或 "aba"
print(longestPalindrome("cbbd")) # 输出: "bb"
Java 实现
public class LongestPalindrome {
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) return "";
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
// 奇数长度的回文子串
int len1 = expandAroundCenter(s, i, i);
// 偶数长度的回文子串
int len2 = expandAroundCenter(s, i, i + 1);
// 取最大长度
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private int expandAroundCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
return right - left - 1;
}
public static void main(String[] args) {
LongestPalindrome solution = new LongestPalindrome();
System.out.println(solution.longestPalindrome("babad")); // 输出: "bab" 或 "aba"
System.out.println(solution.longestPalindrome("cbbd")); // 输出: "bb"
}
}
C++ 实现
#include <string>
using namespace std;
class Solution {
public:
string longestPalindrome(string s) {
if (s.empty()) return "";
int start = 0, end = 0;
for (int i = 0; i < s.size(); i++) {
// 奇数长度的回文子串
int len1 = expandAroundCenter(s, i, i);
// 偶数长度的回文子串
int len2 = expandAroundCenter(s, i, i + 1);
// 取最大长度
int len = max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substr(start, end - start + 1);
}
private:
int expandAroundCenter(const string& s, int left, int right) {
while (left >= 0 && right < s.size() && s[left] == s[right]) {
left--;
right++;
}
return right - left - 1;
}
};
// 测试
int main() {
Solution solution;
cout << solution.longestPalindrome("babad") << endl; // 输出: "bab" 或 "aba"
cout << solution.longestPalindrome("cbbd") << endl; // 输出: "bb"
return 0;
}
代码说明
-
中心扩展法:
- 对于每个字符,尝试以它为中心(奇数长度)或以它和下一个字符为中心(偶数长度)扩展,找到最长的回文子串。
- 使用
expandAroundCenter
函数实现扩展逻辑。
-
时间复杂度:
- 每个字符作为中心最多扩展
n
次,因此时间复杂度为O(n^2)
。
- 每个字符作为中心最多扩展
-
空间复杂度:
- 只使用了常数空间,空间复杂度为
O(1)
。
- 只使用了常数空间,空间复杂度为
测试示例
- 输入
s = "babad"
,输出"bab"
或"aba"
。 - 输入
s = "cbbd"
,输出"bb"
。