Palindrome,也就是回文,指从前向后和从后向前读取都相同的字符串、数字或序列。
例如:
racecar
level
madam
1221都是回文。
而:
hello
algorithm
1234不是。
回文判断虽然简单,却是学习 Two Pointers(双指针) 的经典问题。
方法一:反转字符串
最简单的方法是将字符串反转后与原字符串比较。
function isPalindrome(value: string): boolean {
return value === value.split("").reverse().join("");
}复杂度:
Time: O(n)
Space: O(n)因为需要创建新的反转字符串。
方法二:Two Pointers
更节省空间的方法是在字符串两端各放一个指针。
r a c e c a r
↑ ↑
L R如果两个字符相同,就向中间移动。
function isPalindrome(value: string): boolean {
let left = 0;
let right = value.length - 1;
while (left < right) {
if (value[left] !== value[right]) {
return false;
}
left++;
right--;
}
return true;
}复杂度:
Time: O(n)
Space: O(1)忽略空格和标点符号
一个经典示例是:
A man, a plan, a canal: Panama转换为小写并移除非字母数字字符后:
amanaplanacanalpanama它是回文。
也可以不创建新的字符串,而是在双指针移动过程中直接跳过无效字符。
数字回文
例如:
121
1221
4554也属于 Palindrome。
除了转成字符串,还可以从数学上反转数字:
function isNumberPalindrome(value: number): boolean {
if (value < 0) return false;
const original = value;
let reversed = 0;
while (value > 0) {
const digit = value % 10;
reversed = reversed * 10 + digit;
value = Math.floor(value / 10);
}
return original === reversed;
}递归方法
也可以递归比较字符串两端,然后继续检查内部区间。
时间复杂度仍然是 O(n),但递归调用栈需要额外 O(n) 空间,因此迭代式 Two Pointers 通常更合适。
Almost Palindrome
常见扩展问题是:
最多删除一个字符后,能否让字符串变成回文?
当第一次发现 mismatch 时,可以尝试跳过左侧字符或右侧字符,再判断剩余区间。
相关问题
Palindrome 是许多更复杂问题的基础,例如:
- Longest Palindromic Substring
- Palindromic Subsequence
- Palindrome Partitioning
- Valid Palindrome
- Minimum Insertions
Two Pointers 是通用技巧
双指针还常用于:
- Pair Sum
- Remove Duplicates
- Partitioning
- Array Merge
- Container With Most Water
因此回文判断是学习这一算法模式的良好起点。
大小写问题
Level 是否是回文取决于规则。
区分大小写时 L 与 l 不同;转换成 lowercase 后得到 level。
常见面试题
一个典型题目是:
忽略空格、标点符号和大小写,判断字符串是否为回文。
推荐方案:
Two Pointers
Skip non-alphanumeric characters
Case-insensitive comparison可以实现:
Time: O(n)
Space: O(1)边界情况
"" → true
"a" → true
"aa" → true
"ab" → false
"racecar" → true总结
Palindrome 是一个从两个方向读取都相同的序列。
标准算法使用 Two Pointers:
left → start
right → end
compare
move inward复杂度为:
Time Complexity: O(n)
Space Complexity: O(1)这个问题的重要意义不仅是判断回文,还在于学习对称比较、双指针、边界条件和空间优化等核心算法思维。