一、使用场景:对一个数组进行重复遍历
一般用在数组、单链表等数据结构中
二、关键:判断指针移动的条件
三、类型
1.快慢指针
一快一慢,步长不同。类似于追及问题中的同向追及问题(速度不一)。
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新后的新数组下标的位置
实战:
int removeElement(int* nums, int numsSize, int val) {
int fast=0,slow=0;//定义快慢指针
for (fast=0;fast<numsSize;fast++){
if (nums[fast]!=val) nums[slow++]=nums[fast];}
return slow;//返回移除后数组的新长度
}
2.碰撞指针(有序的数组或链表)
类似于追及问题中的相向相遇问题。
问题:
1.二分查找
2. n数之和
3.滑动窗口
类似计算机网络中的滑动窗口,一般是右端向右扩充,达到停止条件后右端不动,左端向右端逼近,逼近达到停止条件后,左端不动,右端继续扩充。
应用:
- 一般给出的数据结构是数组或者字符串
- 求取某个子串或者子序列最长最短等最值问题或者求某个目标值时
- 该问题本身可以通过暴力求解
- 这类问题可以概括为类似于基于完全满足给定条件的事物的最长序列或最短序列之类
核心思路:
窗口实际是两个指针之间形成的区域,关键——这两个指针是如何移动的。
- 初始时,左右指针left,right都指向第0个元素,窗口为[left,right),注意这里是左闭右开,因此初始窗口[0,0)区间没有元素,符合我们的初始定义
- 开始循环遍历整个数组元素,判断当前right指针是否超过整个数组的长度,是:退出循环,否则:执行第3步
- 然后right指针开始向右移动一个长度,并更新窗口内的区间数据
- 当窗口区间的数据满足我们的要求时,右指针right不变,左指针left开始移动,直到移动到一个不再满足要求的区间时,left不再移动位置
- 执行第2步
注意:窗口的更新与维护是很重要的一环,新元素加入窗口,旧元素移出窗口,都需要及时地更新与这个窗口范围相关的数据。
问题:
1、字符串匹配问题
2、子数组问题
实战:
int minSubArrayLen(int target, int* nums, int numsSize){
int left=0,right=0,sum=0;
int minlength=INT32_MAX;
for (right=0;right<numsSize;right++){
sum+=nums[right];
while (sum>=target){
int sublength=right-left+1;
minlength=minlength=minlength<sublength?minlength:sublength;
sum-=nums[left++];
}
}
return minlength==INT32_MAX?0:minlength;
}