双指针法及题目总结

双指针法与其说是一种算法,不如说是一种思想。

双指针经典题目--在有序数列a中找和为s的两个数。

例如a为 -5,-3,2,4,6,10 求和为1的两个数。答案是【-5,6】【-3,4】

我们用两个指针 l,r 分别指向数列的左右端点。
如果当前 a[l]+a[r]>s 那么我们只能通过 r-- 来使得其和变小。
同样,如果 a[l]+a[r]<s 我们只能通过 l++ 使和变大。
a[l]+a[r]==s 找到一组解。这时候也要改变一下 l 或 r ,让程序继续执行下去,直至 l==r 指针碰撞。

双指针法利用了数据的有序性,使得决策可以通过当前状态推出,提高了效率。

        int l=0; 
        int r=n-1;
        while (l!=r){
            int s=a[l]+a[r];
            if (s<target) l++;
                else if (s>target) r--;
                else {
                    cout<<a[l]<<" "<<a[r]<<endl;
                    l++;
                }
        }

 

更多例题

1.三数之和

https://leetcode-cn.com/problems/3sum/

排序,确定好第一个数,然后双指针取剩下的两个数。

因为要求方案不重复,所以指针必须是跳跃的,要注意越界问题。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& a) {
        sort(a.begin(),a.end());
        int n=a.size();
        vector<int> t(3,0);
        vector<vector<int>> ans;
        int i=0;
        while (i<n-1){
            if (a[i]>0) break; //最下的是正数 那么后边就不需要考虑了
            int tar=-a[i];
            //双指针法在 i+1~n-1中找tar
            int l=i+1;
            int r=n-1;
            while (l<r){ //l的跳跃增长会使得结束条件不一定是l==r
                int sum=a[l]+a[r];
                if (sum<tar) l++;
                else if (sum>tar) r--;
                else{
                    t.clear();
                    t.push_back(a[i]);
                    t.push_back(a[l]);
                    t.push_back(a[r]);
                    ans.push_back(t);
                    while (l<n-1 && a[l]==a[l+1]) l++; l++; //a[l]唯一
                }
            }
            while(i<n-1 && a[i]==a[i+1]) i++; i++; //a[i]唯一
        }
        return ans;
    }
};

2.多多吃饭

最近,碰到了一个这样的题目,也用到了双指针的思想。

有N种午饭和M种晚饭,每种饭都有热量值X和美味值Y,并且每顿饭最多吃一种,问在美味值之和不小于T的情况下,最少的热量摄入X。

原题是拼多多秋招第三题:https://blog.csdn.net/qq_21989927/article/details/107751197

如果饭A的热量值大于B的热量值,并且A的美味值小于B的美味值,那么这个饭A是肯定没有用的,所以我们可以直接不考虑饭A,所以排序完成后,应该是x和y都在递增的情况。

至此,再找出一组或一个y>=T且x的最小值即可。

午饭和晚饭被分为两组,指针l从小到大对午饭遍历,指针r从大到小对晚饭遍历。

我们发现,当前的组合如果满足了T,那么为了求得可能更优的解,我们必须要 r--  用更小的晚饭去匹配当前的午饭。

如果当前的组合不满足T,那么晚饭再怎么选也不能满足(因为r-- 晚饭更小),只能午饭指针 l++。

所以这个题目也可以用双指针完成,复杂度O(n)。

看来双指针有更广泛的应用场景,如果当前的状态判断可以明确决定下一步的判断,并且保证了下一步判断的延续性,数据本身的有序性又保证了这个性质,有点儿像递推【逃】

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值