学习笔记--算法(双指针)5

有效三角形的个数


目录

有效三角形的个数

题目

解法⼀(暴⼒求解)(会超时)

算法思路

代码

[解法二(排序 + 双指针)](#解法二(排序 + 双指针))

算法思路

图解

代码


链接:

. - 力扣(LeetCode)


题目

给定一个包含非负整数的数组 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

解释:

4,2,3

4,2,4

4,3,4

2,3,4

提示:

1 <= nums.length <= 1000

0 <= nums[i] <= 1000


解法⼀(暴力求解)(会超时)


算法思路

三层 for 循环枚举出所有的三元组,并且判断是否能构成三⻆形。虽然说是暴⼒求解,但是还是想优化⼀下:

判断三角形的优化:

▪ 如果能构成三⻆形,需要满⾜任意两边之和要⼤于第三边。但是实际上只需让较⼩的两条边之和⼤于第三边即可。

▪ 因此我们可以先将原数组排序,然后从⼩到⼤枚举三元组,⼀⽅⾯省去枚举的数量,另⼀⽅⾯⽅便判断是否能构成三⻆形。

该算法时间复杂度为O(NlogN + N^3),不排序的算法时间复杂度是:O(3 * N^3)


代码

public int triangleNumber(int[] nums) {
    // 1. 排序
    Arrays.sort(nums);
    int n = nums.length, ret = 0;
    // 2. 从⼩到⼤枚举所有的三元组
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            for (int k = j + 1; k < n; k++) {
                // 当最⼩的两个边之和⼤于第三边的时候,统计答案
                if (nums[i] + nums[j] > nums[k])
                    ret++;
            }
        }
    }
    return ret;
}

解法二(排序 + 双指针)

算法思路

先将数组排序

根据「解法⼀」中的优化思想,我们可以固定⼀个「最⻓边」 ,然后在⽐这条边⼩的有序数组中找出⼀个⼆元组,使这个⼆元组之和⼤于这个最⻓边 。由于数组是有序的,我们可以利⽤**「对撞指针」**来优化。

设最⻓边枚举到 i 位置,区间 [left, right] 是 i 位置左边的区间(也就是⽐它⼩的区间):

1.如果 nums[left] + nums[right] > nums[i]

说明 [left, right - 1] 区间上的所有元素均可以与 nums[right] 构成⽐nums[i] ⼤的⼆元组;

满⾜条件的有 right - left 种;

此时 right 位置的元素的所有情况相当于全部考虑完毕, right-- ,进⼊下⼀轮判断;

2.如果 nums[left] + nums[right] <= nums[i]

说明 left 位置的元素是不可能与 [left + 1, right] 位置上的元素构成满⾜条件的⼆元组;

left 位置的元素可以舍去, left++ 进⼊下轮循环。

该算法的时间复杂度:O(N^2)


图解


代码

public int triangleNumber(int[] nums) {
    // 1. 先排序:
    Arrays.sort(nums);
    // 2. 利⽤双指针解决问题
    int ret = 0;
    int n = nums.length;
    // 先固定最⼤的数
    for(int i = n - 1;i >= 2;i--){
        // 利⽤双指针快速统计出符合要求的三元组的个数,因为再次进入循环的时候,left和right必须回到0和i-1处,所以得定义在循环里
        int left = 0;
        int right = i - 1;
        while(left < right){
            //a+b>c
            if(nums[left] + nums[right] > nums[i]){
                ret += right - left;
                right--;
            }else{
                //a+b<=c
                left++;
            }
        }
    }
    return ret;
}
相关推荐
饮长安千年月2 小时前
Linksys WRT54G路由器溢出漏洞分析–运行环境修复
网络·物联网·学习·安全·机器学习
红花与香菇2____2 小时前
【学习笔记】Cadence电子设计全流程(二)原理图库的创建与设计(上)
笔记·嵌入式硬件·学习·pcb设计·cadence·pcb工艺
尼尔森系4 小时前
排序与算法:希尔排序
c语言·算法·排序算法
AC使者4 小时前
A. C05.L08.贪心算法入门
算法·贪心算法
冠位观测者4 小时前
【Leetcode 每日一题】624. 数组列表中的最大距离
数据结构·算法·leetcode
一天八小时4 小时前
Docker学习进阶
学习·docker·容器
前端没钱4 小时前
前端需要学习 Docker 吗?
前端·学习·docker
拥有一颗学徒的心5 小时前
鸿蒙第三方库MMKV源码学习笔记
笔记·学习·性能优化·harmonyos
yadanuof5 小时前
leetcode hot100 滑动窗口&子串
算法·leetcode
可爱de艺艺5 小时前
Go入门之函数
算法