leetcode
leetcode 501 ~ 550
有效三角形的个数

有效三角形的个数

难度:

标签:

题目描述

代码结果

运行时间: 437 ms, 内存: 16.0 MB


/*
 * 思路:
 * 1. 使用 Java Stream 的方式进行数据处理。
 * 2. 首先将数组进行排序。
 * 3. 然后利用三重循环的方式,通过过滤器(filter)找到满足条件的组合。
 */
 
import java.util.Arrays;
 
public class TriangleNumberStream {
    public long triangleNumber(int[] nums) {
        Arrays.sort(nums); // Step 1: Sort the array
        return IntStream.range(0, nums.length - 2) // Iterate over possible k values
                .flatMap(k -> IntStream.range(0, k) // Iterate over possible j values
                        .flatMap(i -> IntStream.range(i + 1, k) // Iterate over possible i values
                                .filter(j -> nums[i] + nums[j] > nums[k]) // Filter valid triples
                                .count() // Count valid triples for each (i, j, k)
                        )).sum(); // Sum up all counts
    }
}

解释

方法:

这个题解使用了二分查找的思路。首先将数组按升序排序,然后固定最长边 c,用双指针 a 和 b 分别指向最短边和中间边。在 a 和 b 范围内查找符合条件的三角形组合。如果 nums[a] + nums[b] > c,说明存在满足条件的三角形,数量为 b - a,然后将 b 左移缩小范围;否则将 a 右移扩大范围。最后遍历所有可能的最长边 c,将满足条件的三角形数量累加到结果中。

时间复杂度:

O(n^2)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在实现中选择首先对数组进行排序?排序对解题策略有什么影响?
对数组进行排序是为了简化三角形合法性的检查过程。排序后,可以保证任意选取的三个数满足 c >= b >= a,这样只需要检查 a + b > c 是否成立即可。此外,排序使得使用双指针策略成为可能,这样可以有效地减少不必要的组合检查,提高算法效率。
🦆
在选择固定最长边c并使用双指针a和b时,这种方法是否确保了检查所有可能的三元组组合?
是的,该方法通过固定最长边c,并使用双指针a和b(分别指向可能的最短边和中间边),确保了遍历所有可能的三元组组合。双指针从数组的两端向中间移动,能够覆盖所有可能使得 a + b > c 的组合,从而不遗漏任何一个可能的有效三角形。
🦆
为什么当`nums[a] + nums[b] > c`时,可以直接累加`b - a`作为有效的组合数目?这样做的数学逻辑是什么?
当 nums[a] + nums[b] > c 时,由于数组已经排序,说明从指针a到指针b-1的任意一个位置 i,nums[i] + nums[b] 都将大于 c(因为 nums[i] >= nums[a])。因此,对于固定的 b,从 a 到 b-1 的任意位置都可以与 b 形成有效的三角形组合。累加 b - a 是因为这是从 a 到 b-1 的元素个数,即所有满足条件的三元组的数量。
🦆
如果在某次迭代中`nums[a] + nums[b] <= c`,为什么选择移动指针a(最短边)而不是指针b(中间边)?
当 nums[a] + nums[b] <= c 时,说明当前最短边 a 太短,无法与 b 组成有效的三角形。因此需要尝试更大的最短边,即将 a 向右移动,以寻找可能存在的有效组合。移动 b(向左移动)将不会帮助增加 nums[a] + nums[b] 的值,反而可能错过一些有效组合。

相关问题

较小的三数之和

较小的三数之和