【算法学习】-【双指针】-【有效三角形的个数】

LeetCode原题链接:611. 有效三角形的个数

下面是题目描述:
给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

示例 1:
输入: nums = [2,2,3,4]
输出: 3
解释:有效的组合是:
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3

示例 2:
输入: nums = [4,2,3,4]
输出: 4

提示:
1 <= nums.length <= 1000
0 <= nums[i] <= 1000

1、解题思路
本题的解题思路与同类型题【算法学习】-【双指针】-【盛水最多的容器】类似,都是通过双指针利用单调性规律进行求解,本质也是对暴力枚举的一种优化
解题关键主要分为两部分,数学原理及双指针利用单调性,下面逐步进行说明
(1)数学原理
相信大家应该都知道三条边能否构成三角形的条件:任意两条边之和大于第三边。这里用a、b、c表示三条边,那么若a、b、c能构成三角形,则有:

a + b > c
a + c > b
b + c > a

其实我们可以对以上定理进行 “优化”:若a、b、c满足a <= b <= c,则进行如上第一个条件a + b > c的判断即可(因为此时c已经是最大的了),由此我们想要的单调性规律就初见雏形了
(2)利用单调性
那么根据以上结论,我们可先给数据排个序,然后 “固定”住最大的一个数(假设用一个名为end的指针指向它),也就是排序后数组最后一个元素把它作为c边;接着在剩余数中,设置一个指针front指向第一个元素;另一个指针back指向 “固定” 的那个元素的前一个元素,把它们分别作a边和b边。故此时可分为两种情况:

  • a + b <= c
    由于数组是有序的,此时的b,也就是指针back指向的那个数,已经是剩余数中最大的那个数了,故此时若 “固定 ”住a,将b向内枚举b会越来越小a+b的值也就越来越小,此时怎么也不可能构成三角形了。故根据单调性,此时应该将a向内枚举a的值增大了a+b增大,此时才有可能构成三角形
  • a + b > c
    同理,由于数组是有序的,此时的b已经是剩余数中最大的那个数了,故此时若 “固定”住a,将b向内枚举b会减小a+b的值减小,如此一来就不一定构成三角形了。但此时根据单调性我们可以发现,将a向内枚举a+b的值会在大于c的基础上继续增大,也就是说,此时front指针到back指针之间的所有数都能作为a边和b边与c边构成三角形,故此时可以直接将两指针相减进行计数

这里的双指针也可叫做“对撞指针”,也就是当两个指针相遇时,一趟枚举结束;接着改变开始那个固定的最大的数,也就是c边;让end--,其前一个数成为新的c边,开始下一轮的枚举;循环上述过程,直至end前所剩数据量<=1。最终返回计数结果即可。

2、具体代码

    int triangleNumber(vector<int>& nums) 
    {
        sort(nums.begin(),nums.end());
        int end = nums.size() - 1;
        int count = 0;
        while(end > 1)
        {
            int back = end - 1;
            int front = 0;
            while(front != back)
            {
                if(nums[front] + nums[back] > nums[end])
                {
                    count += back - front;
                    back--;
                }
                else
                {
                    front++;
                }
            }

            end--;
        }
        
        return count;

看完觉得有觉得帮助的话不妨点赞收藏鼓励一下,有疑问或看不懂的地方或有可优化的部分还恳请朋友们留个评论,多多指点,谢谢朋友们!🌹🌹🌹

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值