当前位置: 首页 > ds >正文

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 可以知道,对于三元组 (2,3,4) 和 (4,3,2),我们只统计了其中的 (2,3,4),并没有把 (4,3,2) 也统计到答案中,所以题目意思是把这两个三元组当成是同一个三元组,我们不能重复统计。

既然有这样的规则,那么不妨规定三角形的三条边 a,b,c 满足:1 ≤ a ≤ b ≤c
这可以保证我们在统计合法三元组 (a,b,c) 的个数时,不会把 (c,b,a) 这样的三元组也统计进去。

那么问题变成,从 nums 中选三个数,满足 1≤a≤b≤c 且 a+b>c 的方案数。

采用方法:枚举最长边 + 相向双指针

为了能够使用相向双指针,先对数组从小到大排序。 外层循环枚举最长边 c=nums[k],内层循环用相向双指针枚举 a=nums[i] 和 b=nums[j],具体如下:

  1. 初始化左右指针 i=0, j=k−1。
  2. 如果 nums[i]+nums[j]>c,由于数组是有序的,nums[j] 与下标 i' 在 [i,j−1] 中的任何 nums[i'] 相加,都是 >c 的,因此直接找到了 j−i 个合法方案,加到答案中,然后将 j 减一。
  3. 如果 nums[i]+nums[j]≤c,由于数组是有序的,nums[i] 与下标 j' 在 [i+1,j] 中的任何 nums[j'] 相加,都是 ≤c 的,因此后面无需考虑 nums[i],将 i 加一。
  4. 重复上述过程直到 i≥j 为止。

与 LeetCode Hot 100:15. 三数之和-CSDN博客 类似,

在设立相向双指针之前,有两个优化:

作者:灵茶山艾府
链接:https://leetcode.cn/problems/valid-triangle-number/solutions/2432875/zhuan-huan-cheng-abcyong-xiang-xiang-shu-1ex3/
来源:力扣(LeetCode)

答案

/*** @param {number[]} nums* @return {number}*/
var triangleNumber = function(nums) {nums.sort((a, b) => a - b);let ans = 0;for(let k = nums.length - 1; k > 1; k--) {    //倒序枚举if(nums[0] + nums[1] > nums[k]) {    //最小两数之和都大于最大数(边)ans += (k+1) * k * (k-1) / 6;    //任选三条边都可以构成一个三角形break;}if(nums[k-2] + nums[k-1] <= nums[k]) continue;    //次大两数之和都小于最大数let i = 0, j = k - 1;while(i < j) {if(nums[i] + nums[j] > nums[k]) {    //从nums[i]到nums[j-1]都可以作为最短边ans += j - i;j--;    //找新的第二短边} else {i++;    //找新的最短边}}}return ans;
};

复杂度分析

时间复杂度:O(n^2),其中 n 为 nums 的长度。

空间复杂度:O(1)。不计入排序的栈开销,仅用到若干额外变量。

http://www.xdnf.cn/news/17344.html

相关文章:

  • VGG16训练和测试Fashion和CIFAR10
  • Verilog 仿真问题:打拍失败
  • jdk动态代理如何实现
  • 对 .NET线程 异常退出引发程序崩溃的反思
  • 八股——IM项目
  • C++ 运算符重载:避免隐式类型转换的艺术
  • 译 | 在 Python 中从头开始构建 Qwen-3 MoE
  • 【ArcGIS】分区统计中出现Null值且Nodata无法忽略的问题以及shp擦除(erase)的使用——以NDVI去水体为例
  • 最新教程 | CentOS 7 下 MySQL 8 离线部署完整手册(含自动部署脚本)
  • vite项目中集成vditor文档编辑器
  • 低代码系统的技术深度:超越“可视化操作”的架构与实现挑战
  • 【机器学习篇】02day.python机器学习篇Scikit-learn基础操作
  • 疯狂星期四文案网第30天运营日记
  • 自学嵌入式 day43 中断系统
  • 数据结构与算法的认识
  • Linux 防火墙(firewalld)详解与配置
  • 【概念学习】早期神经网络
  • IPS知识点
  • spring-dubbo
  • ##Anolis OS 8.10 安装oracle19c
  • 从零开始的CAD|CAE开发: 单柱绕流+多柱绕流
  • vue封装一个cascade级联 多选 全选组件 ,原生写法Input,Checkbox,Button
  • 看不见的伪造痕迹:AI时代的鉴伪攻防战
  • Codeforces Round 987 (Div. 2)
  • 数据结构—队列和栈
  • 问题定位排查手记1 | 从Windows端快速检查连接状态
  • Java面试宝典:类加载器分层设计与核心机制解析
  • PyCharm vs. VSCode 到底哪个更好用
  • C++、STL面试题总结(二)
  • 图论(邻接表)DFS