每日一题:611. 有效三角形的个数 (中等)

题目:

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

示例 1:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-triangle-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

暴力解法:

一个有效的三角形里任意两边加起来要比第三边长。这个暴力解法利用这个规则。里外循环遍历数组三遍,最里面那层循环检查是否任意两边加起来要比第三边长,如果是,说明我们找到了一个有效的三角形并递增结果。

时间复杂度: O(n^3) 因为有三层循环,所以是n^3的复杂度

空间复杂度: O(1) 

二分查找:

暴力求解时间复杂度太高效率太低,可以试试其他方法。二分查找就是其中之一。有效三角形的规则用数组的方法来表达的话就是:nums[i] + nums[j] > nums[k],其中i,j,k是三个数组元素的下标,代表三条边。我们只要知道其中两条边,就能在剩余数组元素中得出符合这个规则的元素的数量,也就是有效三角形的数量。这里首先对数组排序,然后挑选i和j进行两层循环,在循环中用二分查找找到第一个不符合这个规则的下标k,因为数组是排过序的,所以在k之前的元素肯定都是符合要求的。对结果进行递增.最后返回结果

代码:

class Solution {
public:
    int binarySearch(vector& nums, int l, int r, int target)
    {
        while (r >= l && r < nums.size()) 
        {
            int mid = (l+r)/2;
            if (nums[mid] >= target)
            {
                r = mid-1;
            }
            else
            {
                l = mid+1;
            }
        }
        return l;
    }
    
    int triangleNumber(vector& nums) {
        if (nums.size() < 3)
        {
            return 0;
        }
        
        int res=0;
        sort(nums.begin(), nums.end());
        
        for (int i=0; i < nums.size()-2; i++)
        {
            int k = i+2;
            for (int j = i+1; j < nums.size()-1 && nums[i] > 0; j++)
            {
                // find out where k is invalid
                k = binarySearch(nums, k, nums.size()-1, nums[i]+nums[j]);
                // res += valid range - 1 since we need to exclude k exactly 
                res += k-j-1;
            }
        }
        return res;
    }
};

时间复杂度:O(n^2logn) 排序需要logn时间复杂度,两层循环需要n^2时间复杂度。二分查找最坏情况是O(nlogn),循环n次

空间复杂度 :O(log(n))

双指针:

另一种解法是双指针。和二分查找类似,枚举i和j然后增加k的位置直到k位置的元素不满足条件。增加结果为k-j-1。

代码:

class Solution {
public:
    int triangleNumber(vector& nums) {
        if (nums.size() < 3)
        {
            return 0;
        }
        
        int n = nums.size();
        int res=0;
        sort(nums.begin(), nums.end());
        int k=0;
        
        for (int i=0; i < n-2; i++)
        {
            k = i+2;
            for (int j = i+1; j < n-1 && nums[i] > 0; j++)
            {
                
                // find out where is invalid
                while (k < n && nums[i]+nums[j] > nums[k])
                {
                    k++;
                }
                
                res += k-j-1;
            }
        }
        return res;
    }
};

时间复杂度:O(n^2)

空间复杂度:O(logn)

参考:

https://leetcode.com/problems/valid-triangle-number/

https://leetcode.com/problems/valid-triangle-number/solution/

https://leetcode-cn.com/problems/valid-triangle-number/

https://leetcode-cn.com/problems/valid-triangle-number/solution/you-xiao-san-jiao-xing-de-ge-shu-by-leetcode/

你可能感兴趣的:(每日一题:611. 有效三角形的个数 (中等))