1.双指针
- "双指针" 里的 "指针" 更多是一种逻辑概念,实际实现时通常是用两个变量(如left、right)来表示数组或字符串的下标,通过操作这些下标来模拟指针的移动,从而定位和处理元素。
常⻅的双指针有两种形式,⼀种是对撞指针,⼀种是左右指针。
- 对撞指针:⼀般⽤于顺序结构中,也称左右指针。
- 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼近。
- 对撞指针的终⽌条件⼀般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循 环),也就是:
- left == right (两个指针指向同⼀个位置)
- left > right (两个指针错开)
- 快慢指针:⼜称为⻳兔赛跑算法,其基本思想就是使⽤两个移动速度不同的指针在数组或链表等序列结构上移动。
- 这种⽅法对于处理环形链表或数组⾮常有⽤。 其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使⽤快慢指针的思想。
- 快慢指针的实现⽅式有很多种,最常⽤的⼀种就是:
- 在⼀次循环中,每次让慢的指针向后移动⼀位,⽽快的指针往后移动两位,实现⼀快⼀慢。
相关类型题目


思路:
- 体积(V)=高(H)*宽(W)
- 一个容器能盛多高的水取决于左右两边最短的那块木板
cppH=min(height[left],height[right])
- H不变*W变窄->V变小,假如短的那一边是left,则left和[left+1,right-1]里元素相乘是没有意义的,因为提及一直在变小,而我们求的是最大的体积。
- 所以我们初始化 left=0,right=长度-1,left和right会不断向中间靠拢,直到相遇才停止,每次移动之前会计算出体积,得出体积后让短的那一边向内靠拢,长的那一边则保持不动。
cpp
class Solution {
public:
int maxArea(vector<int>& height) {
// V=H*W;
// H=min(height[left],height[right])
// W=right-left
// min和[left,right]中的任何一个数做容器,只有两种结果
// 1.H不变*W变窄->V变小
// 2.H变小*W变窄->V变小
// 也就是说小的那一个没有和[left,right]里元素相乘的意义
int left=0, right=height.size()-1;
int maxV=0;
while(left<right)
{
maxV=max(maxV,min(height[left],height[right])*(right-left));
height[left]>height[right]?right--:left++;
}
return maxV;
}
};
2.滑动窗口
- 滑动窗口其实一种特殊的双指针。普通双指针往往是相向移动(left从左到右,right从右到左),通过缩小搜索范围来逼近答案;而滑动窗口的left和right则是同向移动(都从左到右),right负责 "扩张" 窗口,left负责 "收缩" 窗口,两者始终保持left ≤ right,共同维护一个连续的子区间。
- 滑动窗口是一种在数组或字符串上高效处理连续子序列问题的算法思想,核心是通过维护一个动态变化的子区间(窗口),在遍历过程中调整窗口的边界(左、右指针),从而在 O (n) 时间复杂度内解决问题,避免暴力解法的 O (n²) 或更高复杂度。
核心思想
- 窗口定义:用两个指针(left、right)表示窗口的左、右边界,窗口范围为 [left, right](闭区间)。
- 进窗口:移动右指针,扩大窗口,直到满足某个条件(如子数组和 >= target)。
- 判断:根据题目条件判断是否需要缩小窗口以继续满足题目条件。
- 出窗口:移动左指针,在满足条件的基础上,缩小窗口以寻找最优解(如最短子数组)。
- 更新结果:过程中实时更新窗口内的关键信息(如和、哈希表计数等),有可能在进窗口的时候更新也有可能在出窗口的时候更新,位置不确定,视题目情况而定。
