29
29
<pre >
30
30
<strong >输入:</strong > nums = [2,2,3,4]
31
31
<strong >输出:</strong > 3
32
- <strong >解释:</strong >有效的组合是:
32
+ <strong >解释:</strong >有效的组合是:
33
33
2,3,4 (使用第一个 2)
34
34
2,3,4 (使用第二个 2)
35
35
2,2,3
@@ -58,13 +58,19 @@ tags:
58
58
59
59
### 方法一:排序 + 二分查找
60
60
61
- 一个有效三角形需要满足:** 任意两边之和大于第三边** 。即:` a + b > c ` 1, ` a + c > b ` 2, ` b + c > a ` 3。
61
+ 一个有效三角形需要满足:** 任意两边之和大于第三边** 。即:
62
62
63
- 如果我们将边按从小到大顺序排列,即 ` a < b < c ` ,那么显然 23 成立,我们只需要确保 1 也成立,就可以形成一个有效三角形。
63
+ $$ a + b \gt c \tag{1} $$
64
64
65
- 我们在 ` [0, n - 3] ` 范围内枚举 i,在 ` [i + 1, n - 2] ` 范围内枚举 j,在 ` [j + 1, n - 1] ` 范围内进行二分查找,找出第一个大于等于 ` nums[i] + nums[j] ` 的下标 left,那么在 ` [j + 1, left - 1] ` 范围内的 k 满足条件,将其累加到结果 ans。
65
+ $$ a + c \gt b \tag{2} $$
66
66
67
- 时间复杂度:$O(n^2\log n)$。
67
+ $$ b + c \gt a \tag{3} $$
68
+
69
+ 如果我们将边按从小到大顺序排列,即 $a \leq b \leq c,ドル那么显然 (2)(3) 成立,我们只需要确保 (1) 也成立,就可以形成一个有效三角形。
70
+
71
+ 我们在 $[ 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}$。
72
+
73
+ 时间复杂度 $O(n^2\log n),ドル空间复杂度 $O(\log n)$。其中 $n$ 是数组的长度。
68
74
69
75
<!-- tabs:start -->
70
76
@@ -88,20 +94,22 @@ class Solution:
88
94
class Solution {
89
95
public int triangleNumber (int [] nums ) {
90
96
Arrays . sort(nums);
91
- int n = nums. length;
92
- int res = 0 ;
93
- for (int i = n - 1 ; i >= 2 ; -- i) {
94
- int l = 0 , r = i - 1 ;
95
- while (l < r) {
96
- if (nums[l] + nums[r] > nums[i]) {
97
- res += r - l;
98
- -- r;
99
- } else {
100
- ++ l;
97
+ int ans = 0 ;
98
+ for (int i = 0 , n = nums. length; i < n - 2 ; ++ i) {
99
+ for (int j = i + 1 ; j < n - 1 ; ++ j) {
100
+ int left = j + 1 , right = n;
101
+ while (left < right) {
102
+ int mid = (left + right) >> 1 ;
103
+ if (nums[mid] >= nums[i] + nums[j]) {
104
+ right = mid;
105
+ } else {
106
+ left = mid + 1 ;
107
+ }
101
108
}
109
+ ans += left - j - 1 ;
102
110
}
103
111
}
104
- return res ;
112
+ return ans ;
105
113
}
106
114
}
107
115
```
@@ -112,12 +120,14 @@ class Solution {
112
120
class Solution {
113
121
public:
114
122
int triangleNumber(vector<int >& nums) {
115
- sort(nums.begin(), nums.end() );
123
+ ranges:: sort(nums);
116
124
int ans = 0, n = nums.size();
117
125
for (int i = 0; i < n - 2; ++i) {
118
126
for (int j = i + 1; j < n - 1; ++j) {
119
- int k = lower_bound(nums.begin() + j + 1, nums.end(), nums[ i] + nums[ j] ) - nums.begin() - 1;
120
- ans += k - j;
127
+ int sum = nums[ i] + nums[ j] ;
128
+ auto it = ranges::lower_bound(nums.begin() + j + 1, nums.end(), sum);
129
+ int k = int(it - nums.begin()) - 1;
130
+ ans += max(0, k - j);
121
131
}
122
132
}
123
133
return ans;
@@ -130,19 +140,15 @@ public:
130
140
```go
131
141
func triangleNumber(nums []int) int {
132
142
sort.Ints(nums)
143
+ n := len(nums)
133
144
ans := 0
134
- for i, n := 0, len(nums) ; i < n-2; i++ {
145
+ for i:= 0; i < n-2; i++ {
135
146
for j := i + 1; j < n-1; j++ {
136
- left, right := j+1, n
137
- for left < right {
138
- mid := (left + right) >> 1
139
- if nums[mid] >= nums[i]+nums[j] {
140
- right = mid
141
- } else {
142
- left = mid + 1
143
- }
147
+ sum := nums[i] + nums[j]
148
+ k := sort.SearchInts(nums[j+1:], sum) + j + 1 - 1
149
+ if k > j {
150
+ ans += k - j
144
151
}
145
- ans += left - j - 1
146
152
}
147
153
}
148
154
return ans
@@ -154,17 +160,14 @@ func triangleNumber(nums []int) int {
154
160
``` ts
155
161
function triangleNumber(nums : number []): number {
156
162
nums .sort ((a , b ) => a - b );
157
- let n = nums .length ;
163
+ const n = nums .length ;
158
164
let ans = 0 ;
159
- for (let i = n - 1 ; i >= 2 ; i -- ) {
160
- let left = 0 ,
161
- right = i - 1 ;
162
- while (left < right ) {
163
- if (nums [left ] + nums [right ] > nums [i ]) {
164
- ans += right - left ;
165
- right -- ;
166
- } else {
167
- left ++ ;
165
+ for (let i = 0 ; i < n - 2 ; i ++ ) {
166
+ for (let j = i + 1 ; j < n - 1 ; j ++ ) {
167
+ const sum = nums [i ] + nums [j ];
168
+ let k = _ .sortedIndex (nums , sum , j + 1 ) - 1 ;
169
+ if (k > j ) {
170
+ ans += k - j ;
168
171
}
169
172
}
170
173
}
@@ -179,56 +182,26 @@ impl Solution {
179
182
pub fn triangle_number (mut nums : Vec <i32 >) -> i32 {
180
183
nums . sort ();
181
184
let n = nums . len ();
182
- let mut res = 0 ;
183
- for i in (2 .. n ). rev () {
184
- let mut left = 0 ;
185
- let mut right = i - 1 ;
186
- while left < right {
187
- if nums [left ] + nums [right ] > nums [i ] {
188
- res += right - left ;
189
- right -= 1 ;
190
- } else {
191
- left += 1 ;
192
- }
193
- }
194
- }
195
- res as i32
196
- }
197
- }
198
- ```
199
-
200
- <!-- tabs: end -->
201
-
202
- <!-- solution: end -->
203
-
204
- <!-- solution: start -->
205
-
206
- ### 方法二
207
-
208
- <!-- tabs: start -->
209
-
210
- #### Java
211
-
212
- ``` java
213
- class Solution {
214
- public int triangleNumber (int [] nums ) {
215
- Arrays . sort(nums);
216
- int ans = 0 ;
217
- for (int i = 0 , n = nums. length; i < n - 2 ; ++ i) {
218
- for (int j = i + 1 ; j < n - 1 ; ++ j) {
219
- int left = j + 1 , right = n;
220
- while (left < right) {
221
- int mid = (left + right) >> 1 ;
222
- if (nums[mid] >= nums[i] + nums[j]) {
223
- right = mid;
224
- } else {
185
+ let mut ans = 0 ;
186
+ for i in 0 .. n . saturating_sub (2 ) {
187
+ for j in i + 1 .. n . saturating_sub (1 ) {
188
+ let sum = nums [i ] + nums [j ];
189
+ let mut left = j + 1 ;
190
+ let mut right = n ;
191
+ while left < right {
192
+ let mid = (left + right ) / 2 ;
193
+ if nums [mid ] < sum {
225
194
left = mid + 1 ;
195
+ } else {
196
+ right = mid ;
226
197
}
227
198
}
228
- ans += left - j - 1 ;
199
+ if left > j + 1 {
200
+ ans += (left - 1 - j ) as i32 ;
201
+ }
229
202
}
230
203
}
231
- return ans;
204
+ ans
232
205
}
233
206
}
234
207
```
0 commit comments