题目重点:找连续回文子串,通过奇偶两类中心覆盖所有候选,并明确并列选择。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练大小写敏感、返回连续substring,多个同长度结果取最早起点;空串返回空。字符串不能在中间跳过字符。
解题路线
- 每个字符是奇数回文中心,相邻间隙是偶数回文中心。对每中心同时向左右扩展,只要字符相同就得到更长合法连续回文。
- 任意非空回文都有唯一中心(字符或间隙),因此所有中心被枚举后不会漏掉最优。每次更新最好(start,length),并列用start最小固定输出,不随遍历偶然决定。
- 返回用一次切片,不在每个扩展步复制候选字符串,否则额外引入substring复制成本。索引是码点位置,Unicode组合字符如需按视觉字符比较需先规范化/切分。
- 如果追问线性算法,Manacher记录每中心半径与最右回文覆盖区,利用镜像半径初值只扩展超过已有边界的部分;应证明全局右边界只向前而非仅报O(n)。本示例保留易核对的中心扩展基线。
手动走一遍
babad有bab与aba长度3,最早起点规则返回bab。cbbd必须检查偶中心得到bb;aaaa扩展中很多重叠候选,但最终长度4;abc返回a。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def longest_palindrome(text):
"""Case sensitive, earliest start breaks equal-length ties."""
best_start=0;best_len=0
for center in range(len(text)):
for left,right in ((center,center),(center,center+1)):
while left>=0 and right<len(text) and text[left]==text[right]:
length=right-left+1
if length>best_len or length==best_len and left<best_start:
best_start=left;best_len=length
left-=1;right+=1
return text[best_start:best_start+best_len]
复杂度
2n−1有效中心,每中心最坏O(n)扩展,总O(n²)时间、O(1)辅助空间;返回切片O(L)输出空间。Manacher可O(n)时间/O(n)半径空间,不能把中心扩展宣称线性。
易错点与追问
容易失分的边界
- 只检查单字符中心漏掉所有偶数长度回文。
- 最长回文子序列bbbb不能作为bbbab的连续答案。
继续深挖
- 在线逐字符追加时如何更新最长回文?回文树可维护不同回文节点,但复杂度与实现合同需另讲。
- 若并列取字典序最小,要把字符串比较开销计入复杂度。
