算法:有效三角形的个数

747 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

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

1.  数组长度不超过1000
2.  数组里整数的范围为 [0, 1000]

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

分析

构成三角形的条件:

任意两条边的和大于第三条边,任意两条边的差小于第三条边

1. 暴力循环

暴力的三层循环查找,在每一层的值当做是三角形的一条边,然后再去判断三个值是否满足构成三角形的条件

function getCount (array) {
    const L = array.length;
    let count = 0;
    for(let i = 0; i<L-2; i++) {
        // 第一条边
        const first = array[i];
        for(let m = i + 1; m<L-1; m ++ ) {
             // 第二条边
            const second = array[m];
            for(let n = m+1; n< L; n++) {
                // 第三条边
                const third = array[n];
                // 判断是否满足三角形的条件
                if(first + second > third && first + third > second && second + third > first) {
                    count ++ ;
                }
            }
        }
    }

    return count;
}

2. 排序 + 双指针

将数组进行从小到大的排序。 固定一条边,另外两条边依次的向右移动。

  1. 我们使用一重循环枚举 i。当 i 固定时,我们使用双指针同时维护 jk,它们的初始值均为 i
  2. 我们每一次将 j 向右移动一个位置,即 j + 1,并尝试不断向右移动 k,使得 k 是最大的满足array[k] < array[i] + array[j],我们将 Math.max(k - j, 0) 累加。

指针 k 不会出现在指针 j 的右侧,即 k - j ≤ 0

function getCount(array) {
    const n = array.length;
    array.sort((a, b) => a - b);
    let count = 0;
    for (let i = 0; i < n; ++i) {
        let k = i;
        for (let j = i + 1; j < n; ++j) {
            while (k + 1 < n && array[k + 1] < array[i] + array[j]) {
                ++k;
            }
            count += Math.max(k - j, 0);
        }
    }
    return count;
};

结语

如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。

文章如有错误之处,希望在评论区指正🙏🙏。

附: