雙指針
顧名思義,兩個指針
做了很多題,一般有兩種模式
一種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;
}
}