diff --git a/solution/0600-0699/0611.Valid Triangle Number/README.md b/solution/0600-0699/0611.Valid Triangle Number/README.md index b0a4484b8ecd2..d1e5b0ef74e07 100644 --- a/solution/0600-0699/0611.Valid Triangle Number/README.md +++ b/solution/0600-0699/0611.Valid Triangle Number/README.md @@ -29,7 +29,7 @@ tags:
输入: nums = [2,2,3,4]
输出: 3
-解释:有效的组合是:
+解释:有效的组合是:
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3
@@ -58,13 +58,19 @@ tags:
### 方法一:排序 + 二分查找
-一个有效三角形需要满足:**任意两边之和大于第三边**。即:`a + b > c`①, `a + c > b`②, `b + c > a`③。
+一个有效三角形需要满足:**任意两边之和大于第三边**。即:
-如果我们将边按从小到大顺序排列,即 `a < b < c`,那么显然 ②③ 成立,我们只需要确保 ① 也成立,就可以形成一个有效三角形。
+$$a + b \gt c \tag{1}$$
-我们在 `[0, n - 3]` 范围内枚举 i,在 `[i + 1, n - 2]` 范围内枚举 j,在 `[j + 1, n - 1]` 范围内进行二分查找,找出第一个大于等于 `nums[i] + nums[j]` 的下标 left,那么在 `[j + 1, left - 1]` 范围内的 k 满足条件,将其累加到结果 ans。
+$$a + c \gt b \tag{2}$$
-时间复杂度:$O(n^2\log n)$。
+$$b + c \gt a \tag{3}$$
+
+如果我们将边按从小到大顺序排列,即 $a \leq b \leq c$,那么显然 (2)(3) 成立,我们只需要确保 (1) 也成立,就可以形成一个有效三角形。
+
+我们在 $[0, n - 3]$ 范围内枚举 i,在 $[i + 1, n - 2]$ 范围内枚举 j,在 $[j + 1, n - 1]$ 范围内进行二分查找,找出第一个大于等于 $nums[i] + nums[j]$ 的下标 left,那么在 $[j + 1, left - 1]$ 范围内的 k 满足条件,将其累加到结果 $\textit{ans}$。
+
+时间复杂度 $O(n^2\log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组的长度。
@@ -88,20 +94,22 @@ class Solution:
class Solution {
public int triangleNumber(int[] nums) {
Arrays.sort(nums);
- int n = nums.length;
- int res = 0;
- for (int i = n - 1; i >= 2; --i) {
- int l = 0, r = i - 1;
- while (l < r) {
- if (nums[l] + nums[r] > nums[i]) {
- res += r - l;
- --r;
- } else {
- ++l;
+ int ans = 0;
+ for (int i = 0, n = nums.length; i < n - 2; ++i) {
+ for (int j = i + 1; j < n - 1; ++j) {
+ int left = j + 1, right = n;
+ while (left < right) {
+ int mid = (left + right) >> 1;
+ if (nums[mid] >= nums[i] + nums[j]) {
+ right = mid;
+ } else {
+ left = mid + 1;
+ }
}
+ ans += left - j - 1;
}
}
- return res;
+ return ans;
}
}
```
@@ -112,12 +120,14 @@ class Solution {
class Solution {
public:
int triangleNumber(vector& nums) {
- sort(nums.begin(), nums.end());
+ ranges::sort(nums);
int ans = 0, n = nums.size();
for (int i = 0; i < n - 2; ++i) {
for (int j = i + 1; j < n - 1; ++j) {
- int k = lower_bound(nums.begin() + j + 1, nums.end(), nums[i] + nums[j]) - nums.begin() - 1;
- ans += k - j;
+ int sum = nums[i] + nums[j];
+ auto it = ranges::lower_bound(nums.begin() + j + 1, nums.end(), sum);
+ int k = int(it - nums.begin()) - 1;
+ ans += max(0, k - j);
}
}
return ans;
@@ -130,19 +140,15 @@ public:
```go
func triangleNumber(nums []int) int {
sort.Ints(nums)
+ n := len(nums)
ans := 0
- for i, n := 0, len(nums); i < n-2; i++ {
+ for i := 0; i < n-2; i++ {
for j := i + 1; j < n-1; j++ {
- left, right := j+1, n
- for left < right {
- mid := (left + right) >> 1
- if nums[mid] >= nums[i]+nums[j] {
- right = mid
- } else {
- left = mid + 1
- }
+ sum := nums[i] + nums[j]
+ k := sort.SearchInts(nums[j+1:], sum) + j + 1 - 1
+ if k > j {
+ ans += k - j
}
- ans += left - j - 1
}
}
return ans
@@ -154,17 +160,14 @@ func triangleNumber(nums []int) int {
```ts
function triangleNumber(nums: number[]): number {
nums.sort((a, b) => a - b);
- let n = nums.length;
+ const n = nums.length;
let ans = 0;
- for (let i = n - 1; i >= 2; i--) {
- let left = 0,
- right = i - 1;
- while (left < right) {
- if (nums[left] + nums[right] > nums[i]) {
- ans += right - left;
- right--;
- } else {
- left++;
+ for (let i = 0; i < n - 2; i++) {
+ for (let j = i + 1; j < n - 1; j++) {
+ const sum = nums[i] + nums[j];
+ let k = _.sortedIndex(nums, sum, j + 1) - 1;
+ if (k > j) {
+ ans += k - j;
}
}
}
@@ -179,56 +182,26 @@ impl Solution {
pub fn triangle_number(mut nums: Vec) -> i32 {
nums.sort();
let n = nums.len();
- let mut res = 0;
- for i in (2..n).rev() {
- let mut left = 0;
- let mut right = i - 1;
- while left < right {
- if nums[left] + nums[right] > nums[i] {
- res += right - left;
- right -= 1;
- } else {
- left += 1;
- }
- }
- }
- res as i32
- }
-}
-```
-
-
-
-
-
-
-
-### 方法二
-
-
-
-#### Java
-
-```java
-class Solution {
- public int triangleNumber(int[] nums) {
- Arrays.sort(nums);
- int ans = 0;
- for (int i = 0, n = nums.length; i < n - 2; ++i) {
- for (int j = i + 1; j < n - 1; ++j) {
- int left = j + 1, right = n;
- while (left < right) {
- int mid = (left + right) >> 1;
- if (nums[mid] >= nums[i] + nums[j]) {
- right = mid;
- } else {
+ let mut ans = 0;
+ for i in 0..n.saturating_sub(2) {
+ for j in i + 1..n.saturating_sub(1) {
+ let sum = nums[i] + nums[j];
+ let mut left = j + 1;
+ let mut right = n;
+ while left < right {
+ let mid = (left + right) / 2;
+ if nums[mid] < sum {
left = mid + 1;
+ } else {
+ right = mid;
}
}
- ans += left - j - 1;
+ if left > j + 1 {
+ ans += (left - 1 - j) as i32;
+ }
}
}
- return ans;
+ ans
}
}
```
diff --git a/solution/0600-0699/0611.Valid Triangle Number/README_EN.md b/solution/0600-0699/0611.Valid Triangle Number/README_EN.md
index 282cd1ec4a45c..71f290a9365b9 100644
--- a/solution/0600-0699/0611.Valid Triangle Number/README_EN.md
+++ b/solution/0600-0699/0611.Valid Triangle Number/README_EN.md
@@ -28,7 +28,7 @@ tags:
Input: nums = [2,2,3,4]
Output: 3
-Explanation: Valid combinations are:
+Explanation: Valid combinations are:
2,3,4 (using the first 2)
2,3,4 (using the second 2)
2,2,3
@@ -55,7 +55,21 @@ tags:
-### Solution 1
+### Solution 1: Sorting + Binary Search
+
+A valid triangle must satisfy: **the sum of any two sides is greater than the third side**. That is:
+
+$$a + b \gt c \tag{1}$$
+
+$$a + c \gt b \tag{2}$$
+
+$$b + c \gt a \tag{3}$$
+
+If we arrange the sides in ascending order, i.e., $a \leq b \leq c$, then obviously conditions (2) and (3) are satisfied. We only need to ensure that condition (1) is also satisfied to form a valid triangle.
+
+We enumerate $i$ in the range $[0, n - 3]$, enumerate $j$ in the range $[i + 1, n - 2]$, and perform binary search in the range $[j + 1, n - 1]$ to find the first index $left$ that is greater than or equal to $nums[i] + nums[j]$. Then, the values of $k$ in the range $[j + 1, left - 1]$ satisfy the condition, and we add them to the result $\textit{ans}$.
+
+The time complexity is $O(n^2\log n)$, and the space complexity is $O(\log n)$, where $n$ is the length of the array.
@@ -79,20 +93,22 @@ class Solution:
class Solution {
public int triangleNumber(int[] nums) {
Arrays.sort(nums);
- int n = nums.length;
- int res = 0;
- for (int i = n - 1; i >= 2; --i) {
- int l = 0, r = i - 1;
- while (l < r) {
- if (nums[l] + nums[r] > nums[i]) {
- res += r - l;
- --r;
- } else {
- ++l;
+ int ans = 0;
+ for (int i = 0, n = nums.length; i < n - 2; ++i) {
+ for (int j = i + 1; j < n - 1; ++j) {
+ int left = j + 1, right = n;
+ while (left < right) {
+ int mid = (left + right) >> 1;
+ if (nums[mid] >= nums[i] + nums[j]) {
+ right = mid;
+ } else {
+ left = mid + 1;
+ }
}
+ ans += left - j - 1;
}
}
- return res;
+ return ans;
}
}
```
@@ -103,12 +119,14 @@ class Solution {
class Solution {
public:
int triangleNumber(vector& nums) {
- sort(nums.begin(), nums.end());
+ ranges::sort(nums);
int ans = 0, n = nums.size();
for (int i = 0; i < n - 2; ++i) {
for (int j = i + 1; j < n - 1; ++j) {
- int k = lower_bound(nums.begin() + j + 1, nums.end(), nums[i] + nums[j]) - nums.begin() - 1;
- ans += k - j;
+ int sum = nums[i] + nums[j];
+ auto it = ranges::lower_bound(nums.begin() + j + 1, nums.end(), sum);
+ int k = int(it - nums.begin()) - 1;
+ ans += max(0, k - j);
}
}
return ans;
@@ -121,19 +139,15 @@ public:
```go
func triangleNumber(nums []int) int {
sort.Ints(nums)
+ n := len(nums)
ans := 0
- for i, n := 0, len(nums); i < n-2; i++ {
+ for i := 0; i < n-2; i++ {
for j := i + 1; j < n-1; j++ {
- left, right := j+1, n
- for left < right {
- mid := (left + right) >> 1
- if nums[mid] >= nums[i]+nums[j] {
- right = mid
- } else {
- left = mid + 1
- }
+ sum := nums[i] + nums[j]
+ k := sort.SearchInts(nums[j+1:], sum) + j + 1 - 1
+ if k > j {
+ ans += k - j
}
- ans += left - j - 1
}
}
return ans
@@ -145,17 +159,14 @@ func triangleNumber(nums []int) int {
```ts
function triangleNumber(nums: number[]): number {
nums.sort((a, b) => a - b);
- let n = nums.length;
+ const n = nums.length;
let ans = 0;
- for (let i = n - 1; i >= 2; i--) {
- let left = 0,
- right = i - 1;
- while (left < right) {
- if (nums[left] + nums[right] > nums[i]) {
- ans += right - left;
- right--;
- } else {
- left++;
+ for (let i = 0; i < n - 2; i++) {
+ for (let j = i + 1; j < n - 1; j++) {
+ const sum = nums[i] + nums[j];
+ let k = _.sortedIndex(nums, sum, j + 1) - 1;
+ if (k > j) {
+ ans += k - j;
}
}
}
@@ -170,56 +181,26 @@ impl Solution {
pub fn triangle_number(mut nums: Vec) -> i32 {
nums.sort();
let n = nums.len();
- let mut res = 0;
- for i in (2..n).rev() {
- let mut left = 0;
- let mut right = i - 1;
- while left < right {
- if nums[left] + nums[right] > nums[i] {
- res += right - left;
- right -= 1;
- } else {
- left += 1;
- }
- }
- }
- res as i32
- }
-}
-```
-
-
-
-
-
-
-
-### Solution 2
-
-
-
-#### Java
-
-```java
-class Solution {
- public int triangleNumber(int[] nums) {
- Arrays.sort(nums);
- int ans = 0;
- for (int i = 0, n = nums.length; i < n - 2; ++i) {
- for (int j = i + 1; j < n - 1; ++j) {
- int left = j + 1, right = n;
- while (left < right) {
- int mid = (left + right) >> 1;
- if (nums[mid] >= nums[i] + nums[j]) {
- right = mid;
- } else {
+ let mut ans = 0;
+ for i in 0..n.saturating_sub(2) {
+ for j in i + 1..n.saturating_sub(1) {
+ let sum = nums[i] + nums[j];
+ let mut left = j + 1;
+ let mut right = n;
+ while left < right {
+ let mid = (left + right) / 2;
+ if nums[mid] < sum {
left = mid + 1;
+ } else {
+ right = mid;
}
}
- ans += left - j - 1;
+ if left > j + 1 {
+ ans += (left - 1 - j) as i32;
+ }
}
}
- return ans;
+ ans
}
}
```
diff --git a/solution/0600-0699/0611.Valid Triangle Number/Solution.cpp b/solution/0600-0699/0611.Valid Triangle Number/Solution.cpp
index 1fbf4a37f0895..781b0cd7f010f 100644
--- a/solution/0600-0699/0611.Valid Triangle Number/Solution.cpp
+++ b/solution/0600-0699/0611.Valid Triangle Number/Solution.cpp
@@ -1,14 +1,16 @@
class Solution {
public:
int triangleNumber(vector& nums) {
- sort(nums.begin(), nums.end());
+ ranges::sort(nums);
int ans = 0, n = nums.size();
for (int i = 0; i < n - 2; ++i) {
for (int j = i + 1; j < n - 1; ++j) {
- int k = lower_bound(nums.begin() + j + 1, nums.end(), nums[i] + nums[j]) - nums.begin() - 1;
- ans += k - j;
+ int sum = nums[i] + nums[j];
+ auto it = ranges::lower_bound(nums.begin() + j + 1, nums.end(), sum);
+ int k = int(it - nums.begin()) - 1;
+ ans += max(0, k - j);
}
}
return ans;
}
-};
\ No newline at end of file
+};
diff --git a/solution/0600-0699/0611.Valid Triangle Number/Solution.go b/solution/0600-0699/0611.Valid Triangle Number/Solution.go
index 8e84d4f8aa7a8..08610a58fdbcb 100644
--- a/solution/0600-0699/0611.Valid Triangle Number/Solution.go
+++ b/solution/0600-0699/0611.Valid Triangle Number/Solution.go
@@ -1,19 +1,15 @@
func triangleNumber(nums []int) int {
sort.Ints(nums)
+ n := len(nums)
ans := 0
- for i, n := 0, len(nums); i < n-2; i++ {
+ for i := 0; i < n-2; i++ {
for j := i + 1; j < n-1; j++ {
- left, right := j+1, n
- for left < right {
- mid := (left + right) >> 1
- if nums[mid] >= nums[i]+nums[j] {
- right = mid
- } else {
- left = mid + 1
- }
+ sum := nums[i] + nums[j]
+ k := sort.SearchInts(nums[j+1:], sum) + j + 1 - 1
+ if k > j {
+ ans += k - j
}
- ans += left - j - 1
}
}
return ans
-}
\ No newline at end of file
+}
diff --git a/solution/0600-0699/0611.Valid Triangle Number/Solution.rs b/solution/0600-0699/0611.Valid Triangle Number/Solution.rs
index e35b77bab6711..7811373f9a465 100644
--- a/solution/0600-0699/0611.Valid Triangle Number/Solution.rs
+++ b/solution/0600-0699/0611.Valid Triangle Number/Solution.rs
@@ -2,19 +2,25 @@ impl Solution {
pub fn triangle_number(mut nums: Vec) -> i32 {
nums.sort();
let n = nums.len();
- let mut res = 0;
- for i in (2..n).rev() {
- let mut left = 0;
- let mut right = i - 1;
- while left < right {
- if nums[left] + nums[right] > nums[i] {
- res += right - left;
- right -= 1;
- } else {
- left += 1;
+ let mut ans = 0;
+ for i in 0..n.saturating_sub(2) {
+ for j in i + 1..n.saturating_sub(1) {
+ let sum = nums[i] + nums[j];
+ let mut left = j + 1;
+ let mut right = n;
+ while left < right {
+ let mid = (left + right) / 2;
+ if nums[mid] < sum {
+ left = mid + 1;
+ } else {
+ right = mid;
+ }
+ }
+ if left > j + 1 {
+ ans += (left - 1 - j) as i32;
}
}
}
- res as i32
+ ans
}
}
diff --git a/solution/0600-0699/0611.Valid Triangle Number/Solution.ts b/solution/0600-0699/0611.Valid Triangle Number/Solution.ts
index 522ad0c45d473..c67688099d9e2 100644
--- a/solution/0600-0699/0611.Valid Triangle Number/Solution.ts
+++ b/solution/0600-0699/0611.Valid Triangle Number/Solution.ts
@@ -1,16 +1,13 @@
function triangleNumber(nums: number[]): number {
nums.sort((a, b) => a - b);
- let n = nums.length;
+ const n = nums.length;
let ans = 0;
- for (let i = n - 1; i >= 2; i--) {
- let left = 0,
- right = i - 1;
- while (left < right) {
- if (nums[left] + nums[right] > nums[i]) {
- ans += right - left;
- right--;
- } else {
- left++;
+ for (let i = 0; i < n - 2; i++) {
+ for (let j = i + 1; j < n - 1; j++) {
+ const sum = nums[i] + nums[j];
+ let k = _.sortedIndex(nums, sum, j + 1) - 1;
+ if (k > j) {
+ ans += k - j;
}
}
}
diff --git a/solution/0600-0699/0611.Valid Triangle Number/Solution2.java b/solution/0600-0699/0611.Valid Triangle Number/Solution2.java
deleted file mode 100644
index 13a17cbea293c..0000000000000
--- a/solution/0600-0699/0611.Valid Triangle Number/Solution2.java
+++ /dev/null
@@ -1,21 +0,0 @@
-class Solution {
- public int triangleNumber(int[] nums) {
- Arrays.sort(nums);
- int ans = 0;
- for (int i = 0, n = nums.length; i < n - 2; ++i) {
- for (int j = i + 1; j < n - 1; ++j) {
- int left = j + 1, right = n;
- while (left < right) {
- int mid = (left + right) >> 1;
- if (nums[mid] >= nums[i] + nums[j]) {
- right = mid;
- } else {
- left = mid + 1;
- }
- }
- ans += left - j - 1;
- }
- }
- return ans;
- }
-}
\ No newline at end of file