算法技巧:双指针总结(2)

本文所涉及的题目的核心思想都是:双指针结合单调性

题一:盛最多水的容器

1.1链接

11. 盛最多水的容器 - 力扣(LeetCode)

1.2思路

前提知识:

  1. 数组名为height
  2. 木桶装多少水取决于短板的长度
  1.  首先,我们先定义两个指针,一个为left,一个为right,体积V=h*w(h为高,w为宽)left = 0,right = height.size ( ) - 1,我们先计算此时的V为多少,然后再去分析,
  2. 若我们将长板往后(或前)挪一位,则其h可能发生的变化是不变或者变得更小,并且此时宽度也在减小,故体积V一定减小;
  3. 若我们把短板往后(或前)挪一位,体积V有变大的可能
  4. 故我们每计算好一个V后,就对短板进行挪动操作,看那个V更大,再去更新最大值

 1.到这,可能大家还会有疑问,就是那为什么要挪短板了?

这是因为我们如果继续挪长板的操作,是没有任何意义的,我们最终要找到的是最大值。

 1.3代码实现
class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0, right = height.size() - 1;
        long long int ret = 0;
        while (left < right) {
            long long int v = min(height[left], height[right]) * (right - left);
            ret = max(ret, v);
            if (height[right] < height[left])
                right--;
            else {
                left++;
            }
        }
        return ret;
    }
};

题二:有效三角形的个数

1.1链接

611. 有效三角形的个数 - 力扣(LeetCode)

1.2思路

 前提知识:

  • 判断一个三角形,是任意二边之和大于第三边
  • 对于已知大小的 a>=b>=c ,则只要保证 b+c>a 就可以
  •  首先先对数组进行排序,将数组排成升序,并创建2个左右指针和count=0
  • 然后,我们在固定一个数c,我们数组后面往前去固定;left=0,right=固定数字的下标减1,sum = nums[left] + nums[right]
  • 我们再去判断sum和c的关系,如果sum>c,那么此时count+=right-left,是因为++后,得到的 nums[left] 大于之前的值,一定可以构成三角形
  • 如果sum<=c,那么此时我们希望sum要大一点,由于数组此时是升序,那么则就是要将left++;
  • 当left>=right,就结束一次判断,再固定另一个数,进行相同的操作

 小优化:由于构成三角形一定要三个数,则我们 i>=2,没必要 i>0

1.3代码
class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int count = 0;
        for (int i = nums.size() - 1; i >= 2; i--) {
            int left = 0;
            int right = i - 1;
            int c = nums[i];
            while (left < right) {
                if (nums[left] + nums[right] > c) {
                    count += right - left;
                    right--;
                } else {
                    left++;
                }
            }
        }
        return count;
    }
};

 题三:三数之和

1.1链接

15. 三数之和 - 力扣(LeetCode)

1.2思路

这里的基本思路与题二一样,只是比较对象换了,操作换了。其他都是一样的。

  • 这里要注意的是要进行排重,首先由于数组经过排序处理的,已经排好了升序;
  • 那么我们在处理left和right的排重的时候,如果left++后下标所对应的值,与之前下标所对应的值相同,则left++,这里要保证left<right,这是为了不发生越界;
  • 如果right--后下标所对应的值,与之前下标所对应的值相同,则right--,这里要保证left<right,这是为了不发生越界
  • 接下来进行固定的数的排重,i++后下标所对应的值,与之前下标所对应的值相同,则i++,这里也要保证i<n,这是为了不发生越界;
1.3代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> arr;
        int n = nums.size();
        for (int i = 0; i < n;) {
            if (nums[i] > 0)
                break;
            int left = i + 1;
            int right = n - 1;
            int c = -nums[i];
            while (left < right) {
                int sum = nums[left] + nums[right];
                if (sum < c)
                    left++;
                else if (sum > c)
                    right--;
                else {
                    arr.push_back({nums[left], nums[right], nums[i]});
                    left++;
                    right--;
                    //排重  left和right
                    while (left < right && nums[left] == nums[left - 1])
                        left++;
                    while (right > left && nums[right] == nums[right + 1])
                        right--;
                }
            }

            //排重i
            i++;
            while (i < n && nums[i] == nums[i - 1])
                i++;
        }

        return arr;
    }
};

  • 54
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值