611. Valid Triangle Number

1. Description

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.

2. Example

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

3. Note

  • The length of the given array won’t exceed 1000.
  • The integers in the given array are in the range of [0, 1000].

4. Solutions

My Accepted Solution

n = m_nums.size()
Time complexity: O($n^2log_2n$)
Space complexity: O(1)

class Solution {
public:
    // int triangleNumber(vector<int>& nums)
    int triangleNumber(vector<int>& m_nums) {
        // the condition of edges to form a triangle is the sum of any two edges is greater than
        // the third edge, and the difference of any edges is less than the third edge, to
        // simplify the condition, we sort all edges. therefore, if a,b,c(the index of a is less
        // than the index of b, the index of b is less than the index of c) match the condition
        // a + b > c, then these three edges must could form a triangle
        sort(m_nums.begin(), m_nums.end());

        int count = 0;
        for (int i = 0; i + 2 < m_nums.size();
             ++i) {  // use i + 2 < m_nums.size() rather than
                     // i < m_nums.size() - 2, if the m_nums.size() is less than 2, it will overflow
            while (i < m_nums.size() && m_nums[i] <= 0) {
                i++;  // all edges should have a positive length
            }

            for (int j = i + 1; j + 1 < m_nums.size(); ++j) {
                auto iter =
                        lower_bound(m_nums.begin() + j + 1, m_nums.end(), m_nums[i] + m_nums[j]);
                int k = iter - m_nums.begin();

                count += k - j - 1;
            }
        }

        return count;
    }
};

4.1 Two Pointers

n = m_nums.size()
Time complexity: O($n^2$)
Space complexity: O(1)

class Solution {
public:
    // int triangleNumber(vector<int>& nums)
    int triangleNumber(vector<int>& m_nums) {
        // the condition of edges to form a triangle is the sum of any two edges is greater than
        // the third edge, and the difference of any edges is less than the third edge, to
        // simplify the condition, we sort all edges. therefore, if a,b,c(the index of a is less
        // than the index of b, the index of b is less than the index of c) match the condition
        // a + b > c, then these three edges must could form a triangle
        sort(m_nums.begin(), m_nums.end());

        int count = 0;
        for (int i = 0; i + 2 < m_nums.size();
             ++i) {  // use i + 2 < m_nums.size() rather than i <
                     // m_nums.size() - 2, if the m_nums.size() is less than 2, it will overflow
            while (i < m_nums.size() && m_nums[i] <= 0) {
                i++;  // all edges should have a positive length
            }

            int k = i + 2;
            for (int j = i + 1; j + 1 < m_nums.size(); ++j) {
                while (k < m_nums.size() && m_nums[i] + m_nums[j] > m_nums[k]) {
                    // even we have two loops here, while these two loops' time complexity is O(n). that's because k will not return to the j + 1, it just continue to increase. within the j's loop, it will increase, now that our array is sorted, its value must increase as well, so there is no need for k to go back to j + 1, it just need to increase to find a bigger valid number to form a triangle
                    ++k;
                }

                count += k - j - 1;
            }
        }

        return count;
    }
};
Last updated:
Tags: Array
comments powered by Disqus