本人是刷《代码随想录》这本书时记录一下自己的学习笔记
双指针有多种用法:
1、快慢指针
2、滑动窗口;
3、左右指针;
注意:当有想使用暴力来解题时,想一下是否可以用双指针,如果问题构成单调性时,可以使用双指针
力扣27
暴力解法:
public int removeElement(int[] nums, int val) {
int count = nums.length; //记录新数组的长度
for(int i = 0;i<count;){
if(nums[i] == val){
for(int j = i+1;j<count;j++){
nums[j-1] = nums[j];//覆盖前一个元素
}
count--;
}else{
i++;//应对情况{2,2},只有找不到val值时才移动i值
}
}
return count;
}
快慢指针:
public int removeElement(int[] nums, int val) {
int slow = 0;//慢指针是用来记录新数组
for(int fast=slow;fast<nums.length;fast++){//快指针是用来遍历所有元素
//快指针不等于删除值时才把指向的值给到慢指针
if(nums[fast]!=val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
滑动窗口
力扣209
思路:首先右指针先向右找到在窗口内符合题目中相加大于等于target的子数组,左指针在向右走,直到子数组中的值相加不在满足大于等于target的条件,左右指针内的元素构成一个滑动窗口的样子
public int minSubArrayLen(int target, int[] nums) {
int min = nums.length+1;
int sum = 0;
int right = 0;
int left = 0;
for(;right<nums.length;right++){
sum+=nums[right];
while(sum >= target){
if((right-left+1) < min){
min = right-left+1;
}
sum-=nums[left];
left++;//左指针开始移动,形成滑动窗口
}
}
if(min==nums.length+1){
return 0;
}
return min;
//这段代码的时间复杂度为O(n)
}
左右指针
力扣977题
分析:
这道题可以用暴力解法,先每个数平方后,在进行排序,但时间复杂度一定不是O(n),因为排序算法的时间复杂度至少是O(nlogn)
数组本来是有序的证明平方后的数组,最大值要么在最左,要么在最右,所以我们可以考虑双指针法,找到平方后的最大值放入新数组,这道题典型是用空间换时间
public int[] sortedSquares(int[] nums) {
int[] arr = new int[nums.length];
int i = 0; //左指针
int j = nums.length-1; //右指针
int k = nums.length-1; //新数组记录
while(i<=j){
if(nums[i]*nums[i] < nums[j]*nums[j]){
arr[k--] = nums[j]*nums[j];
j--;
}else{
arr[k--] = nums[i]*nums[i];
i++;
}
}
return arr;
}
总结
快慢指针:一个快指针和一个慢指针可以用一个for循环完成两个for循环的工作(条件是具有单调性)
滑动窗口:不断调节子序列的起始位置和终止位置,起始位置和终止位置的区间不可间断