class Solution:
def triangleNumber(self, nums):
nums.sort()
n = len(nums)
count = 0
for k in range(n - 1, 1, -1):
i, j = 0, k - 1
while i < j:
if nums[i] + nums[j] > nums[k]:
count += j - i
j -= 1
else:
i += 1
return count
class Solution {
public:
int triangleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int n = nums.size(), count = 0;
for (int k = n - 1; k >= 2; --k) {
int i = 0, j = k - 1;
while (i < j) {
if (nums[i] + nums[j] > nums[k]) {
count += j - i;
--j;
} else {
++i;
}
}
}
return count;
}
};
class Solution {
public int triangleNumber(int[] nums) {
Arrays.sort(nums);
int n = nums.length, count = 0;
for (int k = n - 1; k >= 2; --k) {
int i = 0, j = k - 1;
while (i < j) {
if (nums[i] + nums[j] > nums[k]) {
count += j - i;
--j;
} else {
++i;
}
}
}
return count;
}
}
var triangleNumber = function(nums) {
nums.sort((a, b) => a - b);
let n = nums.length, count = 0;
for (let k = n - 1; k >= 2; --k) {
let i = 0, j = k - 1;
while (i < j) {
if (nums[i] + nums[j] > nums[k]) {
count += j - i;
--j;
} else {
++i;
}
}
}
return count;
};
Given an array of non-negative integers nums
, where each element represents the length of a side of a triangle, determine how many triplets of indices (i, j, k)
(with i < j < k
) can form a valid triangle. A triplet forms a valid triangle if the sum of any two side lengths is greater than the third side length. Each element in nums
can be used only once per triplet, and the same triplet should not be counted multiple times.
Key constraints:
nums
.nums[i] + nums[j] > nums[k]
, nums[i] + nums[k] > nums[j]
, and nums[j] + nums[k] > nums[i]
.1 <= nums.length <= 1000
, 0 <= nums[i] <= 1000
To solve this problem, we start by recognizing that for any three numbers to form a triangle, the sum of any two must be greater than the third. The brute-force approach would be to check all possible triplets in the array, but this would be inefficient for large arrays (as there are O(n³) triplets).
To optimize, we notice that if we sort the array, the largest side in any triplet will always be at the highest index. This lets us focus on the condition nums[i] + nums[j] > nums[k]
(since the other two conditions are guaranteed by the sorting order). Using two pointers, we can efficiently find all valid pairs for each possible largest side.
The key insight is that, by sorting, we can fix the largest side and search for pairs in the remaining array using a two-pointer approach, reducing the time complexity dramatically.
We use the following steps to efficiently count the number of valid triangles:
(i, j, k)
with i < j < k
, nums[k]
is the largest side.k
from n-1
down to 2
, treat nums[k]
as the largest side.i = 0
and j = k-1
. While i < j
:
nums[i] + nums[j] > nums[k]
, then all pairs between i
and j
are valid for this k
, so increment the count by j - i
and move j
leftward.i
rightward to try a larger value.This approach leverages sorting and two pointers to reduce the number of checks from O(n³) to O(n²).
Let's walk through the algorithm with a sample input: nums = [2, 2, 3, 4]
[2, 2, 3, 4]
k = 3
(nums[3] = 4
), i = 0
, j = 2
:
nums[0] + nums[2] = 2 + 3 = 5 > 4
→ valid. All pairs between i
and j
are valid (since nums[1] + nums[2] = 2 + 3 = 5 > 4
as well). So we add j - i = 2
to our count and move j
to 1
.i = 0
, j = 1
:
nums[0] + nums[1] = 2 + 2 = 4
(not greater than 4), so increment i
to 1
.k = 3
.k = 2
(nums[2] = 3
), i = 0
, j = 1
:
nums[0] + nums[1] = 2 + 2 = 4 > 3
→ valid. Add j - i = 1
to count.2 + 1 = 3
valid triangles: (2,3,4)
, (2,3,4)
(with different indices), and (2,2,3)
.k
takes O(n) time, and we do this for each k
, so total time is O(n²).This optimization makes the solution feasible for input sizes up to 1000.
By sorting the array and using the two-pointer technique, we efficiently count all valid triangle triplets in O(n²) time. The key insight is that sorting allows us to always treat the largest side last, and for each such side, quickly determine how many pairs of smaller sides can combine with it to form a triangle. This approach is both elegant and practical, making it suitable for large input sizes.