双指针
顾名思义,两个指针
做了很多题,一般有两种模式
一种i,j指针分别从头尾向中间
一种是i,j指针分别遍历两个部分
题目一 两数之和
(为了讲解双指针,这题目改成返回[2,7]
当然原题目可以用哈希表快一点)
思路:
排序后,采用双指针,从而代码时间复杂度降到O(nlogn)
i指针从0开始
j指针从最后一位开始
若i指针上的数加上j指针上的数大于k,则j—,
否则i+
代码:
public static int[] twoSum(int[] nums, int target) {
Arrays.sort(nums);
int i=0;
int j=nums.length-1;
while(i<j)
{
if(nums[i]+nums[j]==target)
{
return new int[] {nums[i],nums[j]};
}
else if(nums[i]+nums[j]>target)
{
j--;
}
else if(nums[i]+nums[j]<target)
{
i++;
}
}
return new int[] {};
}
题目二 三数之和
思路
在两数之和的基础上做题,采用双指针可将复杂度降到O(n2)
先排序
t指针到最后一个负数
i指针从t+1开始
j指针从最后一个指针开始
代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int t=0;
List<List<Integer>> a=new ArrayList<>();
if(nums.length==0)
return a;
Arrays.sort(nums);
int q=nums[0];
while(t<nums.length&&nums[t]<0)
{
if(t!=0&&nums[t]==q)
{
t++;
continue;
}
int i=t+1;
int j=nums.length-1;
while(i<j)
{
if(nums[i]+nums[j]==-nums[t])
{
List<Integer> bIntegers=new ArrayList<>();
bIntegers.add(nums[t]);
bIntegers.add(nums[i]);
bIntegers.add(nums[j]);
a.add(bIntegers);
i++;
while(nums[i]==nums[i-1]) i++;
j--;
while(nums[j]==nums[j+1]) j--;
}
else if(nums[i]+nums[j]<-nums[t])
{
i++;
while(nums[i]==nums[i-1]) i++;
}
else {
j--;
while(nums[j]==nums[j+1]) j--;
}
}
q=nums[t];
t++;
}
return a;
}
}
# 题目三 有序数组的平方
思路:
利用双指针i,j,分别从数组两头开始,i遍历负数部分,j遍历正数部分,利用双指针合并,合成所求数组。
代码:
class Solution {
public int[] sortedSquares(int[] A) {
int[] nums=new int[A.length];
int i=0;
int j=A.length-1;
int q=nums.length-1;
while(i<=j)
{
int a=(int) Math.pow(A[i], 2);
int b=(int) Math.pow(A[j], 2);
if(a>=b)
{
nums[q]=a;
i++;
}
else {
nums[q]=b;
j--;
}
q--;
}
return nums;
}
}
题目四 接雨水
思路:
这题很棒!
我思考了很长时间
我认为理解这道题
首先要理解其实质
再理解如何通过双指针结合实质计算形式实现计算
实质:
什么决定了一点存储的雨量?
该点墙高-min(左边最高的墙,右边最高的墙)
如果是正数,那么代表该点存储的雨量
双指针:
我们设置两个指针i,j
分别从数组两边向中间进发
当我们可以确定一点的存储雨量,该指针向下一位置进发。
什么时候可以确定一点的存储雨量?
我们指针在遍历的时候,会存取maxleft,maxright
maxleft它针对i点是一定正确的,naxright是不一定正确的(因为没有遍历完,maxright只是针对j点的maxright)
再次回顾一点存储雨量的实质
假如针对i点 此时maxleft<maxright,说明
i点的雨量可以由maxleft决定
假如针对j点,此时maxright<maxleft,说明
j点的雨量可以由maxright决定
代码:
class Solution {
public int trap(int[] height) {
int sum=0;
int maxleft=0;
int maxright=0;
int i=0;
int j=height.length-1;
while(i<=j)
{
if(maxleft<=maxright)
{
if(maxleft-height[i]>0)
{
sum=sum+maxleft-height[i];
}
if(height[i]>maxleft)
{
maxleft=height[i];
}
i++;
}
else {
if(maxright-height[j]>0)
{
sum=sum+maxright-height[j];
}
if(height[j]>maxright)
{
maxright=height[j];
}
j--;
}
}
return sum;
}
}