1、解题思路
- 中心扩展法:遍历字符串中的每一个字符,将其作为回文中心。向左右两边扩展,检查是否构成回文。考虑奇数长度(中心为一个字符)和偶数长度(中心为两个字符)的回文子串。
- 动态规划:定义 dp[i][j] 表示字符串从 i 到 j 的子串是否是回文。状态转移方程: 如果 A[i] == A[j] 且 dp[i+1][j-1] 为 true,则 dp[i][j] = true。边界条件:单个字符 dp[i][i] = true,两个相同字符 dp[i][i+1] = (A[i] == A[i+1])。
- Manacher算法(进阶要求):线性时间复杂度 O(n),空间复杂度 O(n)。利用对称性和已知信息来避免重复计算。
2、代码实现
C++
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param A string字符串 * @return int整型 */ int getLongestPalindrome(string A) { // write code here int n = A.size(); if (n <= 1) { return n; } int max_len = 1; for (int i = 0; i < n; ++i) { int len1 = expandAroundCenter(A, i, i); // 奇数长度 int len2 = expandAroundCenter(A, i, i + 1); // 偶数长度 max_len = max(max_len, max(len1, len2)); } return max_len; } 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; } };
Java
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param A string字符串 * @return int整型 */ public int getLongestPalindrome (String A) { // write code here if (A == null || A.length() <= 1) return A.length(); int max_len = 1; for (int i = 0; i < A.length(); i++) { int len1 = expandAroundCenter(A, i, i); // 奇数长度 int len2 = expandAroundCenter(A, i, i + 1); // 偶数长度 max_len = Math.max(max_len, Math.max(len1, len2)); } return max_len; } 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; } }
Python
# # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # # @param A string字符串 # @return int整型 # class Solution: def getLongestPalindrome(self , A: str) -> int: # write code here if len(A) <= 1: return len(A) max_len = 1 for i in range(len(A)): len1 = self.expandAroundCenter(A, i, i) # 奇数长度 len2 = self.expandAroundCenter(A, i, i + 1) # 偶数长度 max_len = max(max_len, max(len1, len2)) return max_len def expandAroundCenter(self, s: str, left: int, right: int) -> int: while left >= 0 and right < len(s) and s[left] == s[right]: left -= 1 right += 1 return right - left - 1
3、复杂度分析
关键点说明
- 中心扩展法: 时间复杂度 O(n²),空间复杂度 O(1)。适用于题目要求的 O(n²) 时间复杂度和 O(1) 空间复杂度。
- 动态规划: 时间复杂度 O(n²),空间复杂度 O(n²)。适用于需要记录所有子串是否为回文的情况。
- Manacher算法: 时间复杂度 O(n),空间复杂度 O(n)。适用于题目进阶要求的线性时间复杂度。
复杂度分析
- 中心扩展法: 时间复杂度:O(n²),因为每个字符最多被访问两次。空间复杂度:O(1),仅使用常数个额外变量。
- 动态规划: 时间复杂度:O(n²),需要填充 n×n 的 dp 表格。空间复杂度:O(n²),需要存储 dp 表格。
- Manacher算法: 时间复杂度:O(n),线性遍历字符串。空间复杂度:O(n),需要额外的数组存储信息。
进阶思考
- 如果需要输出最长回文子串本身,可以在扩展过程中记录子串的起始和结束位置。
- 如果需要处理更长的字符串(如
n ≤ 10^6
),应优先选择Manacher
算法。