vault backup: 2026-05-13 14:52:13

This commit is contained in:
2026-05-13 14:52:13 +08:00
parent 76a6b08e8d
commit ed1b490979
3 changed files with 815 additions and 0 deletions
+29
View File
@@ -427,3 +427,32 @@ func joinStrings(words []string, sep string) string {
> - 纯字符串拼接 → `strings.Builder`,接口更简洁,零额外内存拷贝
> - 需要同时处理字节级和字符串级操作 → `bytes.Buffer`
> - Go 1.10+ 才引入了 `strings.Builder`,刷题环境通常已支持
---
## 🧠 今日收获:排序 + 去重的联动思维
源自 [[双指针/06-三数之和]],最核心的启发是:**「排序」不只是为算法服务,更是为「去重」铺路。**
### 为什么排序后去重如此优雅?
排序让**相同的值聚集在一起**。当我们已经遍历过一个值并得到结果后,下一个相同的值必然紧跟其后——只需比较前一个位置就能跳过整个重复段,无需额外空间(如 map 或 set)。
### 三层去重模式
在"固定一点、双指查找"的问题中,每个决策点都可能产生重复解,需要在**每一层都加去重判断**:
| 层级 | 代码 | 时机 |
|------|------|------|
| **外层 i** | `if i > 0 && nums[i] == nums[i-1]: continue` | 枚举固定点时,前驱已作为固定点完整枚举过 |
| **左指针 left** | `left++; while left < right && nums[left] == nums[left-1]: left++` | 找到解后右移,跳过所有与刚走过的 left 相同的值 |
| **右指针 right** | `right--; while left < right && nums[right] == nums[right+1]: right--` | 找到解后左移,跳过所有与刚跳过的 right 相同的值 |
### 关键细节
> [!warning] ⚠️ 容易出错的地方
> 1. **先去重再移动指针 → 漏解**。正确顺序:记录答案 → 去重 → 继续搜索。
> 2. **比较对象要搞对**:left 和 `nums[left-1]` 比(刚走过的),right 和 `nums[right+1]` 比(刚跳过的)。
> 3. **i 的范围是 n-2 而非 n**:最后两个位置留给 left 和 right。
>
> 这条模式可以推广到四数之和(LeetCode 18)、K 数之和——依次固定 k-2 个数,最后两层用双指针收尾,每层都加上同样的去重逻辑即可。