[LeetCode] Valid Triangle Number 合法的三角形个数

简介: Given an array consists of non-negative integers, your task is to count the number of triplets chosen from the array that can make triangles if we take them as side lengths of a triangle.

Given an array consists of non-negative integers, your task is to count the number of triplets chosen from the array that can make triangles if we take them as side lengths of a triangle.

Example 1:

Input: [2,2,3,4]
Output: 3
Explanation:
Valid combinations are: 
2,3,4 (using the first 2)
2,3,4 (using the second 2)
2,2,3

Note:

  1. The length of the given array won't exceed 1000.
  2. The integers in the given array are in the range of [0, 1000]. 

这道题给了我们一堆数字,问我们能组成多少个正确的三角形,我们初中就知道三角形的性质,任意两条边之和要大于第三边。那么问题其实就变成了找出所有这样的三个数字,使得任意两个数字之和都大于第三个数字。那么可以转变一下,三个数字中如果较小的两个数字之和大于第三个数字,那么任意两个数字之和都大于第三个数字,这很好证明,因为第三个数字是最大的,所以它加上任意一个数肯定大于另一个数。这样,我们就先要给数组排序,博主最先尝试了暴力破解法,结果TLE了(不要吐槽博主哈,博主就是喜欢霸王硬上弓~),后来优化的方法是先确定前两个数,将这两个数之和sum作为目标值,然后用二分查找法来快速确定第一个小于目标值的数,这种情况属于博主之前的博客LeetCode Binary Search Summary 二分搜索法小结中总结的第二类的变形,我们找到这个临界值,那么这之前一直到j的位置之间的数都满足题意,直接加起来即可,参见代码如下:

解法一:

public:
    int triangleNumber(vector<int>& nums) {
        int res = 0, n = nums.size();
        sort(nums.begin(), nums.end());
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                int sum = nums[i] + nums[j], left = j + 1, right = n;
                while (left < right) {
                    int mid = left + (right - left) / 2;
                    if (nums[mid] < sum) left = mid + 1;
                    else right = mid;
                }
                res += right - 1 - j;
            }
        }
        return res;
    }
};

其实还有更进一步优化的方法,用的是博主之前那篇3Sum Smaller里面的解法二,明明博主以前都总结过,换个题目情景就又没想到,看来博主的举一反三能力还是有所欠缺啊。没办法,只能继续刻意练习了。这种方法能将时间复杂度优化到O(n2), 感觉很叼了。思路是排序之后,从数字末尾开始往前遍历,将left指向首数字,将right之前遍历到的数字的前面一个数字,然后如果left小于right就进行循环,循环里面判断如果left指向的数加上right指向的数大于当前的数字的话,那么right到left之间的数字都可以组成三角形,这是为啥呢,相当于此时确定了i和right的位置,可以将left向右移到right的位置,中间经过的数都大于left指向的数,所以都能组成三角形,就说这思路叼不叼!加完之后,right自减一,即向左移动一位。如果left和right指向的数字之和不大于nums[i],那么left自增1,即向右移动一位,参见代码如下: 

解法二:

public:
    int triangleNumber(vector<int>& nums) {
        int res = 0, n = nums.size();
        sort(nums.begin(), nums.end());
        for (int i = n - 1; i >= 2; --i) {
            int left = 0, right = i - 1;
            while (left < right) {
                if (nums[left] + nums[right] > nums[i]) {
                    res += right - left;
                    --right;
                } else {
                    ++left;
                }
            }
        }
        return res;
    }
};

参考资料:

https://discuss.leetcode.com/topic/92099/java-o-n-2-time-o-1-space

本文转自博客园Grandyang的博客,原文链接:[LeetCode] Valid Triangle Number 合法的三角形个数

,如需转载请自行联系原博主。

相关文章
|
5月前
|
算法
Leetcode 313. Super Ugly Number
题目翻译成中文是『超级丑数』,啥叫丑数?丑数就是素因子只有2,3,5的数,7 14 21不是丑数,因为他们都有7这个素数。 这里的超级丑数只是对丑数的一个扩展,超级丑数的素因子不再仅限于2 3 5,而是由题目给定一个素数数组。与朴素丑数算法相比,只是将素因子变了而已,解法还是和朴素丑数一致的。
63 1
|
3月前
|
Go
golang力扣leetcode 120.三角形最小路径和
golang力扣leetcode 120.三角形最小路径和
10 0
【LeetCode-每日一题】-120. 三角形最小路径和
【LeetCode-每日一题】-120. 三角形最小路径和
|
5月前
|
存储
Leetcode Single Number II (面试题推荐)
给你一个整数数组,每个元素出现了三次,但只有一个元素出现了一次,让你找出这个数,要求线性的时间复杂度,不使用额外空间。
21 0
|
10月前
|
人工智能 算法 BI
【LeetCode——编程能力入门第二天】运算符(三角形的最大周长(贪心算法)/找到最近的有相同 X 或 Y 坐标的点)
给定由一些正数(代表长度)组成的数组 nums ,返回 由其中三个长度组成的、面积不为零的三角形的最大周长 。如果不能形成任何面积不为零的三角形,返回 0。
75 0
|
12月前
|
Java
力扣120. 三角形最小路径和Java
力扣120. 三角形最小路径和Java
133 0
【力扣每日一题:8-04】611. 有效三角形的个数【中等】
【力扣每日一题:8-04】611. 有效三角形的个数【中等】
LeetCode每日一题(23)——最大三角形面积
最大三角形面积 1.题目 2.示例 3.思路 4.代码 暴力穷举 凸包
LeetCode每日一题(23)——最大三角形面积
|
存储 Python
LeetCode 120. 三角形最小路径和
给定一个三角形 triangle ,找出自顶向下的最小路径和。
90 0
LeetCode contest 190 5417. 定长子串中元音的最大数目 Maximum Number of Vowels in a Substring of Given Length
LeetCode contest 190 5417. 定长子串中元音的最大数目 Maximum Number of Vowels in a Substring of Given Length

热门文章

最新文章