今天不聊人生理想,也不谈前端框架内卷,咱们来一场字符串的花式反转派对!
你以为反转只是 reverse()?No no no~在力扣(LeetCode)的世界里,反转是一门艺术,更是一场修行。
本文带你一口气刷透四道经典字符串反转题,从入门到进阶,从“翻转单词”到“检测重复子串”,边笑边学,笑着通过面试!
🔥 题目一:151. 反转字符串中的单词 —— “倒着说话”的艺术
🎯 题意简述:
输入:" hello world "
输出:"world hello"
要求:去掉多余空格,只保留单词间一个空格,顺序完全颠倒。
💡 思考过程:
很多人第一反应是:split(' ') → filter → reverse → join(' ')。
确实能过,但——面试官微微一笑:“还有更优雅的原地处理方式吗?”
于是我们祭出双指针 + 倒序遍历大法:
var reverseWords = function(s) {
let str = '', res = '';
for (let i = s.length - 1; i >= 0; i--) {
// 拼单词(注意:字符加在前面!)
while (i >= 0 && s[i] !== ' ') {
str = s[i] + str;
i--;
}
if (str) {
res += str + ' ';
str = '';
i++; // 关键回退!
}
}
return res.slice(0, -1); // 删掉最后那个多余的空格
};
🤔 为什么 i++?
因为内层 while 结束时,i 已经指向空格或 -1。外层 for 还会再 i--,所以必须 i++ 抵消一次,不然会漏字符!这步堪称“灵魂回退”。
✅ 小贴士:这种写法不用额外数组,空间 O(1)(忽略结果字符串),时间 O(n),完美!
🔁 题目二:344. 反转字符串 —— 最朴素的浪漫
🎯 题意简述:
把 ["h","e","l","l","o"] 变成 ["o","l","l","e","h"],原地修改,不准开新数组!
💡 解法:左右指针对撞
var reverseString = function(s) {
for (let i = 0, j = s.length - 1; i < j; i++, j--) {
[s[i], s[j]] = [s[j], s[i]]; // ES6 解构交换,优雅永不过时
}
};
⚠️ 注意循环条件是
i < j,不是i < s.length / 2虽然效果一样,但前者更直观!
这题看似简单,却是所有反转操作的基石。记住:对撞指针,yyds!
🔍 题目三:459. 重复的子字符串 —— 字符串的“套娃”检测术
🎯 题意简述:
判断 "abab" 是否由 "ab" 重复构成?
答案:✅ 是!
💡 神仙解法(来自官方脑洞):
把字符串复制一份拼接:ss = s + s
然后去掉首尾字符:newStr = ss.slice(1, -1)
如果 newStr 中还能找到原字符串 s,那它就是重复子串构成的!
var repeatedSubstringPattern = function(s) {
const ss = s + s;
return ss.slice(1, -1).includes(s);
};
🤯 原理揭秘:
假设 s = "abcabc",那么 ss = "abcabcabcabc"
去掉首尾 → "bcabcabcab"
中间依然包含 "abcabc"!
因为重复结构在拼接后会产生“冗余匹配窗口” 。
这招叫 KMP 的民间智慧版,虽然没显式用 KMP,但思想异曲同工。面试说出来,面试官眼睛会发光✨!
🧩 题目四:541. 反转字符串 II —— 分段反转,节奏大师
🎯 题意简述:
每 2k 个字符为一组,只反转前 k 个。
比如 "abcdefg", k=2 → "bacdfeg"
💡 解法:分块处理 + 局部反转
var reverseStr = function(s, k) {
let arr = s.split("");
for (let i = 0; i < arr.length; i += 2 * k) {
let start = i;
let end = Math.min(i + k - 1, arr.length - 1);
while (start < end) {
[arr[start], arr[end]] = [arr[end], arr[start]];
start++;
end--;
}
}
return arr.join("");
};
🎵 节奏感拉满:
i += 2k:每次跳过一个完整周期end = min(i + k - 1, n-1):防止越界- 内部用对撞指针反转前
k个
这题考验你对边界控制和分段逻辑的理解。写对了,说明你已经掌握了“局部操作全局”的思维!
🎉 总结:反转的哲学
| 题号 | 核心思想 | 技巧关键词 |
|---|---|---|
| 151 | 倒序遍历 + 手动拼词 | 回退指针、空格处理 |
| 344 | 对撞指针 | 原地交换 |
| 459 | 字符串自拼接 | 数学构造、包含检测 |
| 541 | 分块 + 局部反转 | 步长控制、边界防御 |
反转不是目的,理解结构才是。
这些题背后,藏着字符串处理的通用范式:双指针、分治、边界处理、空间优化。
💬 最后说两句
刷题不是为了背答案,而是为了培养“看到问题就想到模式”的直觉。
下次遇到字符串,别慌——先问自己:
“我能用双指针吗?需要分段吗?要不要去空格?能不能构造新串?”
答案,往往就在问题之中。