0611. 有效三角形的个数
题目地址(611. 有效三角形的个数)
https://leetcode-cn.com/problems/valid-triangle-number/
题目描述
前置知识
排序
双指针
二分法
三角形边的关系
公司
腾讯
百度
字节
暴力法(超时)
思路
首先要有一个数学前提: 如果三条线段中任意两条的和都大于第三边,那么这三条线段可以组成一个三角形
。即给定三个线段 a,b,c,如果满足 a + b > c and a + c > b and b + c > a,则线段 a,b,c 可以构成三角形,否则不可以。
力扣中有一些题目是需要一些数学前提的,不过这些数学前提都比较简单,一般不会超过高中数学知识,并且也不会特别复杂。一般都是小学初中知识即可。
如果你在面试中碰到不知道的数学前提,可以寻求面试官提示试试。
关键点解析
三角形边的关系
三层循环确定三个线段
代码
代码支持: Python
复杂度分析
时间复杂度:$O(N ^ 3)$,其中 N 为 数组长度。
空间复杂度:$O(1)$
优化的暴力法
思路
暴力法的时间复杂度为 $O(N ^ 3)$, 其中 $N$ 最大为 1000。一般来说, $O(N ^ 3)$ 的算法在数据量 <= 500 是可以 AC 的。1000 的数量级则需要考虑 $O(N ^ 2)$ 或者更好的解法。
OK,到这里了。我给大家一个干货。 应该是其他博主不太会提的。原因可能是他们不知道, 也可能是他们觉得太小儿科不需要说。
由于前面我根据数据规模推测到到了解法的复杂度区间是 $N ^ 2$, $N ^ 2 * logN$,不可能是 $N$ (WHY?)。
降低时间复杂度的方法主要有:
空间换时间
和排序换时间
(我们一般都是使用基于比较的排序方法)。而排序换时间
仅仅在总体复杂度大于 $O(NlogN)$ 才适用(原因不用多说了吧?)。
这里由于总体的时间复杂度是 $O(N ^ 3)$,因此我自然想到了排序换时间
。当我们对 nums 进行一次排序之后,我发现:
is_triangle 函数有一些判断是无效的
因此我们的目标变为找到
a + b > c
即可,因此第三层循环是可以提前退出的。
这也仅仅是减枝而已,复杂度没有变化。通过进一步观察,发现 k 没有必要每次都从 j + 1 开始。而是从上次找到的 k 值开始就行。原因很简单, 当 nums[i] + nums[j] > nums[k] 时,我们想要找到下一个满足 nums[i] + nums[j] > nums[k] 的 新的 k 值,由于进行了排序,因此这个 k 肯定比之前的大(单调递增性),因此上一个 k 值之前的数都是无效的,可以跳过。
由于 K 不会后退,因此最内层循环总共最多执行 N 次,因此总的时间复杂度为 $O(N ^ 2)$。
这种技巧在很多题目中都出现过,值得引起大家的重视。比如 84. 柱状图中最大的矩形 中的 优化中心扩展法
这个复杂度分析有点像单调栈,大家可以结合起来理解。
关键点分析
排序
代码
复杂度分析
时间复杂度:$O(N ^ 2)$
空间复杂度:取决于排序算法
更多题解可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
最后更新于