02_双指针(two points)
简单描述
双指针是这样的模式:一般初始化为left=0,right=len(num)-1,两个指针朝着左右方向移动(双指针分为同向双指针和异向双指针),直到他们有一个或是两个都满足某种条件。
优势
相比较暴力解法穷举,双指针可以过滤掉部分对达成目标无意义的遍历,从而达成优化时间复杂度的作用。
使用场景
-
一般来说,数组或是链表是排好序的,你得在里头找一些组合满足某种限制条件
-
这种组合可能是一对数,三个数,或是一个子数组
-
二分搜索
- 利用左右指针,和mid中间索引,缩小查找范围
-
找到两个数,使两数之和等于输入值(如果数组有序,应该想到双指针)
- 有序,left=0,right=len(num)-1,left右移,num[left] + num[right]变大,right左移,num[left] + num[right]变小,直到找到和输入target相同的值
-
反转数组
-
滑动窗口(也许是双指针的最高境界了)
例子
/***
* leetcode_11_盛最多的水_双指针解法
*
* 左右两边,两个指针同时向对方移动
* 优点:
* 优化时间复杂度,相比较暴力解法,可以过滤掉一些 跟目标相反的遍历(目标是:面积最大)
*
* 做法:固定住 对目标有利的输入(比如j和i索引下的偏大值)。移动对目标不利的输入(比如j和i索引下的偏小值)。这样就达到优化遍历的目的
* @param height
* @return
*/
public int maxArea(int[] height) {
int i=0,j=height.length-1;
//保存最大面积
int maxArea = 0;
while(i<j){
//先更细最大值,在更新游标
maxArea = Math.max(maxArea,(Math.min(height[i],height[j])*(j-i)));
if(height[i] < height[j]){
i++;
}else{
j--;
}
}
return maxArea;
}
/**
* leetcode_977_有序数组的平方_双指针解法
* @param nums
*/
public int[] sortedSquares(int[] nums) {
int[] result = new int[nums.length];
int left = 0;
int right = nums.length-1;
int index = nums.length-1;
while (left<=right){
if(nums[left]*nums[left]>nums[right]*nums[right]){
result[index--] = nums[left]*nums[left];
left++;
}else {
result[index--] = nums[right]*nums[right];
right--;
}
}
return result;
}