优先算法之双指针讲解+刷题路线

双指针

双指针的核心思路

对撞指针:两个指针从序列的两端向中间移动,适用于有序数组或需要从两端逼近的问题。

快慢指针:两个指针从同一端开始,一个移动较快,一个移动较慢,适用于判断条件是否满足比较元素间相对关系的问题。

双指针经典题型:

leetcode:661(有效三角形个数)

解法分析:排序 + 双指针 + 利用单调性

:https://leetcode.cn/problems/valid-triangle-number/icon-default.png?t=O83Ahttps://leetcode.cn/problems/valid-triangle-number/

class Solution {
void quiksort(vector<int>& nums,int l,int r){//快排将数组有序化
if(l >= r)
return;
int i = l - 1, j = r + 1,x = nums[(i + j) >> 1];
while(i < j){
do i++;while(nums[i] < x);
do j--;while(nums[j] > x);
if(i < j)
swap(nums[i],nums[j]);
}
quiksort(nums,l,j);
quiksort(nums,j + 1,r);
}
public:
    int triangleNumber(vector<int>& nums) {
        quiksort(nums,0,nums.size() - 1);
        int sum = 0;
//当数组有序后可以发现
//我们可以确定三个数中的最大值
//然后利用双指针来判断是否满足三角形成立条件
    for(int i = nums.size() - 1;i >= 2;i--){//for循环确定最大值
int l = 0;
int r = i - 1;
while(l < r){//双指针判断是否满足三角形形成条件
if(nums[l] + nums[r] > nums[i]){//如果(nums[l] + num[r] > nums[i])那么里面的数也一定能形成
//三角形
sum += (r - l);
r--;
}else{
//否则的话左指针++增大三个数中的最小值后继续判断
    l++;
}
    }      
    }
        return sum;
}
};

leetcode:LCR179(查找总价格为目标值的两个商品)

解法分析:双指针 + 二分

https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/description/icon-default.png?t=O83Ahttps://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/description/

class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target) {
        int l = 0,r = price.size() - 1;//初始化左右指针
        vector<int> nums;
        while(l < r){
if(price[l] + price[r] < target)//总值小于要找的值l++
l++;
else if(price[l] + price[r] > target)//总值大于要找的值r--
r--;
else{//总值等于要找的值返回
nums.push_back(price[l]);
nums.push_back(price[r]);
return nums;
}
        }
return nums;
    }
};

leetocde:15(三数之和)

https://leetcode.cn/problems/3sum/icon-default.png?t=O83Ahttps://leetcode.cn/problems/3sum/

解法分析:排序 + 枚举 + 双指针  + 去重(set)
class Solution {

void quiksort(vector<int>& nums,int l,int r){//进行一遍快排方便后续使用双指针
    if(l >= r)
    return;
int i = l - 1,j = r + 1,x = nums[(l + r) >> 1];
while(i < j){
    do i++; while(nums[i] < x);
    do j--; while(nums[j] > x);
    if(i < j){
        swap(nums[i],nums[j]);
    }
}
quiksort(nums,l,j);
quiksort(nums,j+1,r);
}
public:
    vector<vector<int>> threeSum(vector<int>& nums) {

        quiksort(nums,0,nums.size() - 1);
        vector<vector<int>> vv;
        set<vector<int>> s;//利用set容器的特性去掉重复的值

        for(int i = 0;i < nums.size()-2;i++){//固定第三个数用双指针来查找接下来的两个数

int l = i + 1,r = nums.size() - 1;

while(l < r){
if(nums[l] + nums[r] == -nums[i]){//当两个指针代表的数之和等于固定的数的负数的时候就是找到了
    s.insert({nums[i],nums[l],nums[r]});//插入
l++;//这里注意要变换两个指针的位置进入下一次循环否则会导致死循环
r--;
}
else if(nums[l] + nums[r]  >  -nums[i])//大于情况
r--;
else//小于情况
l++;
} 
        }
    for(auto& e : s){//for-each把双指针查询得到的每一个数组值插入进vv中
        vv.push_back(e);
    }
    return vv;//返回
    }
};
思考:这道题如果不用set去重的话因该怎么做?
class Solution {

void quiksort(vector<int>& nums,int l,int r){
    if(l >= r)
    return;
int i = l - 1,j = r + 1,x = nums[(l + r) >> 1];
while(i < j){
    do i++; while(nums[i] < x);
    do j--; while(nums[j] > x);
    if(i < j){
        swap(nums[i],nums[j]);
    }
}
quiksort(nums,l,j);
quiksort(nums,j+1,r);
}
public:
    vector<vector<int>> threeSum(vector<int>& nums) {

        quiksort(nums,0,nums.size() - 1);
        vector<vector<int>> vv;
        for(int i = 0;i < nums.size()-2;i++){//遍历第三个数
        if(i > 0 && nums[i] == nums[i-1])//跳过固定数重复的情况
        continue;
int l = i + 1,r = nums.size() - 1;
while(l < r){
if(nums[r] + nums[l] == -nums[i]){//找出符合条件的三个数
    vv.push_back({nums[i],nums[l],nums[r]});
    r--;//向中移动
    l++;
    //跳过后面重复的符合条件的数
     while (l < r && nums[l] == nums[l - 1]) l++;
      while (l < r && nums[r] == nums[r + 1]) r--;
}
else if(nums[r] + nums[l] > -nums[i])
{r--;
}
else if(nums[r] + nums[l] < -nums[i])
{l++;

}
}
        }
    return vv;
    }
};
加强训练:leetocde18(四数之和)

题目链接

本人题解链接

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞象帆船

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值