zoukankan      html  css  js  c++  java
  • [LeetCode 611.] Valid Triangle Number

    LeetCode 611. 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.

    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].

    解题思路

    首先想到的是暴力枚举所有的三元组,但是三层循环、并且每个三元组都需要三次三角不等式判断,肯定是不可接受的,所有我们可以有以下优化:

    1. 可以先排序,然后 i<j<k 的约束条件下,就只需要判断 nums[i] + nums[j] > nums[k] 这一个不等式就可以了;
    2. 又注意到数组有序,这样当某一个k不满足条件,后续的k都将不满足条件,可以提前结束 k 循环;
    3. 在有序数组中,前半段满足条件后半段不满足条件的判断,可以用二分查找进一步优化。

    参考代码

    对于优化1和优化2,我们有以下代码:

    /*
     * @lc app=leetcode id=611 lang=cpp
     *
     * [611] Valid Triangle Number
     */
    
    // @lc code=start
    class Solution {
    public:
        int triangleNumber(vector<int>& nums) {
            size_t n = nums.size();
            int cnt = 0;
            sort(nums.begin(), nums.end());
            for (int i=0; i+2<n; i++) {
                for (int j=i+1; j+1<n; j++) {
                    for (int k=j+1; k<n; k++) {
                        if (nums[i] + nums[j] <= nums[k]) {
                            break;
                        }
                        cnt ++;
                    }
                }
            }
            return cnt;
        } // AC, O(N^3)
    };
    // @lc code=end
    

    加入优化3,代码如下:

    /*
     * @lc app=leetcode id=611 lang=cpp
     *
     * [611] Valid Triangle Number
     */
    
    // @lc code=start
    class Solution {
    public:
        int triangleNumber(vector<int>& nums) {
            size_t n = nums.size();
            int cnt = 0;
            sort(nums.begin(), nums.end());
            for (int i=0; i+2<n; i++) {
                for (int j=i+1; j+1<n; j++) {
                    auto start = nums.begin()+j+1;
                    auto it = lower_bound(start, nums.end(), nums[i]+nums[j]);
                    cnt += it - start;
                }
            }
            return cnt;
        } // AC, O(N^2 * logN)
    // lower_bound 二分查找返回元素第一次出现位置,或者第一个大于该元素的位置
    };
    // @lc code=end
    
  • 相关阅读:
    关于Token
    利用Chrome模拟访问移动端网页
    文件上传
    final修饰符
    后台返回字符串类型function的处理 (递归算法)
    javascript typeof
    单点登录的原理与简单实现
    response.setHeader()的用法
    UML类图6种关系的总结
    子类父类属性的覆盖(继承)
  • 原文地址:https://www.cnblogs.com/zhcpku/p/14586675.html
Copyright © 2011-2022 走看看