有效三角形的个数

99 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情

题目描述

给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

示例

输入: nums = [2,2,3,4]
输出: 3
解释: 有效的组合是: 
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3
输入: nums = [4,2,3,4]
输出: 4

提示

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

排序 + 二分查找

假设有三条边,从小到大依次为i,j,k。如果k的长度小于i + j,那么,这三条边必定无法构建成一个三角形。

根据上面的结论,我们可以将数组按照从小到大进行排序,这样即可以利用二分查找来快速定位到当前组合的边界点,统计出符合条件的三元组个数。

步骤:

  1. 先将数组进行排序
  2. 遍历数组,当前指针i表示为三条边中最短的一条边
  3. 第二层遍历,当前指针j表示为三条边的中间值
  4. 二分查找,通过取中间点比较,判断当前组合是否符合三角形,每次排除剩余一半的元素
  5. 累加结果
class Solution {
    public int triangleNumber(int[] nums) {
        int max = 0, n = nums.length;
        // 将数组排序
        Arrays.sort(nums);
        
        // 遍历数组,i 表示三角形中第一条边
        for(int i = 0; i < n - 2; ++i){
            // 遍历数组,j 表示三角形中第二条边
            for(int j = i + 1; j < n - 1; ++j){
                // 二分查找
                int left = j + 1, right = n - 1, k = j;
                while(left <= right){
                    // 取中间点
                    int mid = (right + left) >> 1;
                    // 判断符合条件,则指针右移,统计左边元素
                    if(nums[mid] < nums[i] + nums[j]){
                        k = mid;
                        left = mid + 1;
                    }else{
                        // 不符合条件,指针左移,舍弃右边的元素
                        right = mid - 1;
                    }
                }
                // 结果累加
                max += k - j;
            }
        }

        return max;
    }
}