双指针(Two Pointers) 是编程里非常经典、也非常实用的一种技巧,尤其在数组、字符串、链表这类线性结构中出镜率超高。
循环的本质,就是用一个“指针”变量,按照某种规律(顺序、条件)移动,依次访问或处理一系列数据。
但是当循环中出现循环的嵌套时,时间复杂度就会指数上升,暴力解决不是不可以,但是却不能一直如此
一、什么是双指针?
核心思想一句话:
用两个指针(索引 / 引用)在同一个数据结构上协同移动,减少不必要的重复遍历。
相比一个指针从头扫到尾,双指针往往能把
- 时间复杂度从 O(n²) 降到 O(n)
- 或者让逻辑更清晰、代码更优雅
二、常见的双指针类型
1.对撞指针(左右指针)
特点:
- 一个指针从左边开始
- 一个指针从右边开始
- 不断向中间靠拢
典型场景:
- 有序数组
- 回文判断
- 两数之和(已排序)
2.快慢指针(Fast & Slow)
特点:
- 两个指针同向移动
- 速度不同(1步 / 2步)
典型场景:
- 链表是否有环
- 找链表中点
- 删除倒数第 N 个节点
2.滑动窗口(本质也是双指针)
特点:
- 两个指针维护一个区间
[left, right) - 窗口可扩张 / 收缩
典型场景:
- 子数组 / 子串问题
- 连续区间最大值、最小值
- 满足某种条件的最短 / 最长区间
三、什么时候该想到双指针?
你可以用这几个触发关键词来判断
- 有序数组
- 连续区间 / 子数组 / 子串
- 需要降低时间复杂度
- 不能用额外空间(O(1) 空间)
- 链表相关问题
四、注意事项
- 注意边界条件:要小心处理数组或链表为空、只有一个元素等边界情况,防止数组越界;需要明确定义循环何时结束,通常是
left < right或fast != nil