🧠 引言
在字符串算法题中,有两个“面试必考”问题:
- 判断一个字符串是否是回文
- 找出最长不含重复字符的子串
这两题虽然简单,但却是滑动窗口 + 双指针 + 字符哈希三大算法思想的交汇点。
本篇将用 JS 与 Python 双语方式,带你彻底掌握它们!
🧪 Part 1:回文字符串判断(LeetCode 125)
❓题目描述
判断一个字符串是否是回文串,只考虑字母和数字字符,忽略大小写。
输入: "A man, a plan, a canal: Panama"
输出: true
✅ 解法思路(双指针)
- 两个指针从头尾向中间移动
- 跳过非字母数字字符
- 比较字符是否相等(需忽略大小写)
💻 JavaScript 实现
function isPalindrome(s) {
let left = 0, right = s.length - 1;
while (left < right) {
while (left < right && !/[a-zA-Z0-9]/.test(s[left])) left++;
while (left < right && !/[a-zA-Z0-9]/.test(s[right])) right--;
if (s[left].toLowerCase() !== s[right].toLowerCase()) return false;
left++;
right--;
}
return true;
}
🐍 Python 实现
def is_palindrome(s):
left, right = 0, len(s) - 1
while left < right:
while left < right and not s[left].isalnum():
left += 1
while left < right and not s[right].isalnum():
right -= 1
if s[left].lower() != s[right].lower():
return False
left += 1
right -= 1
return True
🧪 Part 2:最长不重复子串(LeetCode 3)
❓题目描述
给定字符串 s,请找出其中不含重复字符的最长子串的长度。
输入: "abcabcbb"
输出: 3 ("abc")
✅ 解法思路(滑动窗口)
- 用
start和end表示当前窗口的左右边界 - 用哈希表记录字符出现位置
- 每次遇到重复字符时,移动
start - 实时更新最大长度
💻 JavaScript 实现
function lengthOfLongestSubstring(s) {
let map = {};
let maxLen = 0, start = 0;
for (let end = 0; end < s.length; end++) {
const char = s[end];
if (map[char] >= start) {
start = map[char] + 1;
}
map[char] = end;
maxLen = Math.max(maxLen, end - start + 1);
}
return maxLen;
}
🐍 Python 实现
def length_of_longest_substring(s):
char_map = {}
max_len = start = 0
for end, char in enumerate(s):
if char in char_map and char_map[char] >= start:
start = char_map[char] + 1
char_map[char] = end
max_len = max(max_len, end - start + 1)
return max_len
⚠️ 易错点总结
| 错误点 | 正确写法 |
|---|---|
start 没更新 | 碰到重复字符时需更新到上次位置+1 |
| 回文判断没跳过非法字符 | 用 isalnum() 或正则排除非字母数字字符 |
哈希判断写成 map[char] | 要检查 map[char] >= start |
🧩 拓展任务
- 回文变种题:最长回文子串(中心扩展法)
- 重复字符最多允许出现一次(LeetCode 159)
- 支持中文字符处理(Unicode)
📚 总结一句话
双指针在字符串题中是高频武器,不止解决判断问题,更能优化遍历性能、解锁更难题型!
📘 下一篇预告:
第16篇:【前缀和 + 哈希】JS 与 Python 解“和为 K 的子数组个数”!