LeetCode611. 有效三角形的个数
1. 问题描述
2. 思路
三条长度为 a、b、c 的线段,能够组成三角形的充要条件是:
a
+
b
>
c
a + b > c
a+b>c
a
+
c
>
b
a + c > b
a+c>b
b
+
c
>
a
b + c > a
b+c>a
2.1 思路一
解决本题的过程,就是一个搜索的过程。一种解决方案是,获取nums数组中所有长度为3的组合,判断能否满足上面三角形构成的条件。
上述解决方案是使用暴力回溯的方式,从长度为3的组合中,筛选出能够组成三角形的三元组,时间复杂度较高。另一种思路是,可以利用数组的有序性,来降低搜索过程的时间复杂度。
2.2 思路二
如果三条线段长度分别为 a,b,c ,a < b < c, 一定满足 a + c > b 和 b + c > a。因此,只需满足 a + b > c 就可以构成有效三角形。也就是说,如果确定一条最大的边c,只需满足两条长度较小的边a + b 大于c,就一定能够构成三角形。
- 将数组排序,利用数组的有序性进行搜索。
- 从后向前遍历,取
nums[i]
,作为三角形最大的边c
2.1 对于c,从c前面的所有元素中,找到所有a + b > c
的两条边a和b,个数为n。
2.2 将找到的结果收集起来res += n
。
2.1 可以理解为从有序数组中,找出两个元素a和b,使得a+b>c。统计满足以上情况的<a,b>的个数。可以使用双指针来解决,
- 令left = 0, right = i,如果left < right,进入循环
- 如果
nums[left] + nums[right] > c
,那么nums[left+1] + nums[right]
、nums[left+2] + nums[right]
、一直到nums[right-1] + nums[right]
都大于c,通过res = res + (right - left)
将结果累加到res中;通过right--
,将right左移 - 如果
nums[left] + nums[right] <= c
无法构成三角形,通过left++
,将left右移
- 如果
3. 代码
func triangleNumber(nums []int) int {
var res int
sort.Ints(nums)
for i := len(nums) - 1; i >= 2; i-- {
left, right := 0, i - 1
for left < right {
if nums[left] + nums[right] > nums[i] {
res += right - left
right--
} else {
left++
}
}
}
return res
}