双指针是一种问题建模思路,适用于有序数组的比对问题,可将时间复杂度从O(n²)降至O(n);常见场景包括两数之和、滑动窗口、归并操作及快慢指针变体。

双指针本身不是 for 循环的“优化写法”,而是**一种问题建模思路**,它常借助 for 循环(或 while)实现,在特定场景下能将时间复杂度从 O(n²) 降到 O(n),从而显著提升数组遍历比对效率。关键不在于“怎么用 for 写双指针”,而在于:什么时候该用、怎么设指针、循环怎么控制。
适用场景:哪些比对问题适合双指针
双指针真正起效的前提是数组有序,或可通过排序/预处理获得单调性。常见模式包括:
- 两数之和(有序数组):找两个数使和等于 target
- 滑动窗口类比对:如最长无重复子数组、满足条件的最短子数组
- 归并/合并类操作:合并两个有序数组、求交集、去重合并
- 快慢指针变体:检测环、找中点、删除倒数第 n 个节点(虽非严格“比对”,但属同族技巧)
核心实现:用 while 或 for 控制双指针移动
多数双指针逻辑用 while 更自然(边界清晰、终止条件明确),但也可用 for 模拟——关键是让两个变量(如 left 和 right)独立增减,而非嵌套 for。
以“有序数组中找两数之和”为例(返回下标):
立即学习“Java免费学习笔记(深入)”;
function twoSumSorted(nums, target) {
let left = 0, right = nums.length - 1;
while (left < right) {
const sum = nums[left] + nums[right];
if (sum === target) return [left, right];
if (sum < target) left++; // 和太小 → 左指针右移(增大值)
else right--; // 和太大 → 右指针左移(减小值)
}
return [-1, -1];
}这里没有 for 嵌套,单次遍历完成,时间复杂度 O(n),空间 O(1)。
对比传统 for 嵌套:为什么快
暴力解法用双层 for:
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] === target) return [i, j];
}
}它穷举所有组合,共约 n²/2 次比对;而双指针利用**数组有序性+决策单调性**,每步排除一整行/一整列可能解。比如 left++ 时,意味着 nums[left] 和当前 right 及其右边所有数的组合都不可能达标(因为已偏小),直接跳过。
注意事项:别强行套用
双指针不是万能加速器:
- 无序数组慎用:若强行排序,O(n log n) 预处理可能抵消收益;且原下标会丢失(需额外保存)
- 不满足单调约束不行:比如“找乘积最大两个数”,正负混杂时不能简单用两端比对
- 三数及以上和?考虑固定一维+双指针:如三数之和 → 先 for 固定 i,再对 [i+1, end] 区间用双指针,整体 O(n²)


















