一、快慢指针(同向指针)
1. 核心概念
两个指针 fast 和 slow 从同一侧(通常是索引 0)出发。
- 快指针
fast: 像侦察兵,负责在前面遍历整个数组,寻找符合「保留」条件的元素。 - 慢指针
slow: 像后勤兵,停在需要被替换的位置,只在接收到快指针传来的有效数据时才往前走。
2. 关键词
- 「原地」修改 / 删除 / 去重
- 「移动特定元素到末尾」(如移动 0)
- 核心诉求:需要在 O(n)O(n)O(n) 时间复杂度和 O(1)O(1)O(1) 空间复杂度下完成数组元素的重排。
3. 代码模板
jsx
// 适用场景:把所有符合条件的元素移到前面
let slow = 0;
for (let fast = 0; fast < nums.length; fast++) {
if (/* nums[fast] 是我们需要保留的元素 */) {
// 1. 赋值或交换
nums[slow] = nums[fast];
// 2. 慢指针前进一步,准备接收下一个
slow++;
}
}
// 循环结束后,slow 的值通常就是处理后新数组的长度
练习题目: LeetCode 27(移除元素)、LeetCode 283(移动零)
二、左右指针(对撞指针)
1. 核心概念
两个指针从数组的两端出发,left 在头,right 在尾,相向而行,直到相遇或交错。
2. 关键词
- 「有序数组」+「两数之和 / 查找」(这是最强烈的信号)
- 「反转字符串 / 数组」
- 「回文判断」
3. 代码模板
jsx
let left = 0;
let right = nums.length - 1;
while (left < right) {
let sum = nums[left] + nums[right];
if (sum === target) {
return [left, right]; // 找到目标,直接返回或记录
} else if (sum < target) {
// 和太小,需要更大的数,左指针右移
left++;
} else {
// 和太大,需要更小的数,右指针左移
right--;
}
}
练习题目: LeetCode 344(反转字符串)、LeetCode 167(两数之和 II)