11.12 LeetCode 题目汇总与解题思路
题目一:344. 反转字符串
解法1:单指针法
class Solution {
public:void reverseString(vector<char>& s) {int n = s.size();if (n < 2) return;int left = 0;while (left < n / 2) {char tmp = s[left];s[left] = s[n - left - 1];s[n - left - 1] = tmp;left++;}}
};
特点:
- 使用单个指针
left - 通过
n - left - 1计算对称位置 - 遍历到数组中间即可
解法2:双指针法(更直观)
class Solution {
public:void reverseString(vector<char>& s) {if (s.size() < 2) return;int left = 0, right = s.size() - 1;while (left < right) {char tmp = s[left];s[left] = s[right];s[right] = tmp;left++;right--;}}
};
特点:
- 使用双指针
left和right - 逻辑更清晰直观
- 交换直到指针相遇
题目二:541. 反转字符串 II
解法:分段反转
class Solution {
public:string reverseStr(string s, int k) {for (int i = 0; i < s.size(); i += (k * 2)) {// 需要反转的区间: [i, i+k-1]if (i + k <= s.size()) {reverse(s.begin() + i, s.begin() + i + k); // 反转前k个continue;}reverse(s.begin() + i, s.end()); // 剩余不足k个,全部反转}return s;}
};
算法思路详解
反转字符串 II 的执行逻辑:
输入: s = "abcdefg", k = 2分段处理:
i=0: 反转[0,1] → "bacdefg"
i=4: 反转[4,5] → "bacdfeg"
i=8: 超出范围,结束结果: "bacdfeg"
规则总结:
- 每
2k个字符为一组 - 每组反转前
k个字符 - 剩余字符少于
k个时,全部反转
核心技巧对比
| 技巧 | 适用场景 | 时间复杂度 | 空间复杂度 |
|---|---|---|---|
| 单指针 | 简单反转、对称操作 | O(n) | O(1) |
| 双指针 | 双向遍历、交换操作 | O(n) | O(1) |
| 分段反转 | 固定间隔反转 | O(n) | O(1) |
关键优化点
反转字符串的交换优化:
// 更简洁的交换写法
swap(s[left], s[right]);// 或者使用异或交换(不推荐,可读性差)
s[left] ^= s[right];
s[right] ^= s[left];
s[left] ^= s[right];
反转字符串 II 的边界处理:
// 更简洁的写法
for (int i = 0; i < s.length(); i += 2 * k) {int end = min(i + k, (int)s.length());reverse(s.begin() + i, s.begin() + end);
}
扩展应用
自定义反转函数:
void myReverse(vector<char>& s, int start, int end) {while (start < end) {swap(s[start], s[end]);start++;end--;}
}// 在反转字符串II中使用
if (i + k <= s.size()) {myReverse(s, i, i + k - 1);
}
性能分析
反转字符串:
- 两种解法性能相同
- 双指针法更易理解和维护
反转字符串 II:
- 关键在正确的区间计算
- 注意边界条件的处理
记忆要点
- 双指针模板:
int left = 0, right = n - 1;
while (left < right) {swap(s[left], s[right]);left++; right--;
}
- 分段反转模板:
for (int i = 0; i < n; i += 2*k) {reverse(s, i, min(i + k, n));
}