40
40
41
41
<!-- 这里可写通用的实现逻辑 -->
42
42
43
- 双指针加二分,先枚举两条边,然后利用二分查找定位第三条边。
43
+ ** 方法一:排序 + 二分查找**
44
+
45
+ 一个有效三角形需要满足:** 任意两边之和大于第三边** 。即:` a + b > c ` ①, ` a + c > b ` ②, ` b + c > a ` ③。
46
+
47
+ 如果我们将边按从小到大顺序排列,即 ` a < b < c ` ,那么显然 ②③ 成立,我们只需要确保 ① 也成立,就可以形成一个有效三角形。
48
+
49
+ 我们在 ` [0, n-3] ` 范围内枚举 i,在 ` [i+1, n-2] ` 范围内枚举 j,在 ` [j+1, n-1] ` 范围内进行二分查找,找出第一个大于等于 ` nums[i]+nums[j] ` 的下标 left,那么在 ` [j+1, left-1] ` 范围内的 k 满足条件,将其累加到结果 ans。
50
+
51
+ 时间复杂度 O(n²logn)。
44
52
45
53
<!-- tabs:start -->
46
54
51
59
``` python
52
60
class Solution :
53
61
def triangleNumber (self , nums : List[int ]) -> int :
54
- n = len (nums)
55
62
nums.sort()
56
- ans = 0
63
+ ans, n = 0 , len (nums)
57
64
for i in range (n - 2 ):
58
65
for j in range (i + 1 , n - 1 ):
59
- left, right = j + 1 , n
60
- while left < right:
61
- mid = left + (right - left) // 2
62
- if nums[mid] < nums[i] + nums[j]:
63
- left = mid + 1
64
- else :
65
- right = mid
66
- ans += left - j - 1
66
+ k = bisect_left(nums, nums[i] + nums[j], lo = j + 1 ) - 1
67
+ ans += k - j
67
68
return ans
68
69
```
69
70
@@ -93,6 +94,30 @@ class Solution {
93
94
}
94
95
```
95
96
97
+ ``` java
98
+ class Solution {
99
+ public int triangleNumber (int [] nums ) {
100
+ Arrays . sort(nums);
101
+ int ans = 0 ;
102
+ for (int i = 0 , n = nums. length; i < n - 2 ; ++ i) {
103
+ for (int j = i + 1 ; j < n - 1 ; ++ j) {
104
+ int left = j + 1 , right = n;
105
+ while (left < right) {
106
+ int mid = (left + right) >> 1 ;
107
+ if (nums[mid] >= nums[i] + nums[j]) {
108
+ right = mid;
109
+ } else {
110
+ left = mid + 1 ;
111
+ }
112
+ }
113
+ ans += left - j - 1 ;
114
+ }
115
+ }
116
+ return ans;
117
+ }
118
+ }
119
+ ```
120
+
96
121
### ** TypeScript**
97
122
98
123
``` ts
@@ -120,18 +145,17 @@ function triangleNumber(nums: number[]): number {
120
145
121
146
``` go
122
147
func triangleNumber (nums []int ) int {
123
- n := len (nums)
124
148
sort.Ints (nums)
125
149
ans := 0
126
- for i := 0 ; i < n-2 ; i++ {
150
+ for i , n := 0 , len (nums) ; i < n-2 ; i++ {
127
151
for j := i + 1 ; j < n-1 ; j++ {
128
152
left , right := j+1 , n
129
153
for left < right {
130
- mid := int (uint (left+right) >> 1 )
131
- if nums[mid] < nums[i]+nums[j] {
132
- left = mid + 1
133
- } else {
154
+ mid := (left + right) >> 1
155
+ if nums[mid] >= nums[i]+nums[j] {
134
156
right = mid
157
+ } else {
158
+ left = mid + 1
135
159
}
136
160
}
137
161
ans += left - j - 1
@@ -148,20 +172,13 @@ class Solution {
148
172
public:
149
173
int triangleNumber(vector<int >& nums) {
150
174
sort(nums.begin(), nums.end());
151
- int n = nums.size();
152
- int ans = 0;
153
- for (int i = 0; i < n - 2; ++i) {
154
- for (int j = i + 1; j < n - 1; ++j) {
155
- int left = j + 1, right = n;
156
- while (left < right) {
157
- int mid = left + right >> 1;
158
- if (nums[ mid] < nums[ i] + nums[ j] ) {
159
- left = mid + 1;
160
- } else {
161
- right = mid;
162
- }
163
- }
164
- ans += left - j - 1;
175
+ int ans = 0, n = nums.size();
176
+ for (int i = 0; i < n - 2; ++i)
177
+ {
178
+ for (int j = i + 1; j < n - 1; ++j)
179
+ {
180
+ int k = lower_bound(nums.begin() + j + 1, nums.end(), nums[ i] + nums[ j] ) - nums.begin() - 1;
181
+ ans += k - j;
165
182
}
166
183
}
167
184
return ans;
0 commit comments