2929<pre >
3030<strong >输入:</strong > nums = [2,2,3,4]
3131<strong >输出:</strong > 3
32- <strong >解释:</strong >有效的组合是:
32+ <strong >解释:</strong >有效的组合是:
33332,3,4 (使用第一个 2)
34342,3,4 (使用第二个 2)
35352,2,3
@@ -58,13 +58,19 @@ tags:
5858
5959### 方法一:排序 + 二分查找
6060
61- 一个有效三角形需要满足:** 任意两边之和大于第三边** 。即:` a + b > c ` ①, ` a + c > b ` ②, ` b + c > a ` ③。
61+ 一个有效三角形需要满足:** 任意两边之和大于第三边** 。即:
6262
63- 如果我们将边按从小到大顺序排列,即 ` a < b < c ` ,那么显然 ②③ 成立,我们只需要确保 ① 也成立,就可以形成一个有效三角形。
63+ $$ a + b \gt c \tag{1} $$
6464
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} $$
6666
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$ 是数组的长度。
6874
6975<!-- tabs:start -->
7076
@@ -88,20 +94,22 @@ class Solution:
8894class Solution {
8995 public int triangleNumber (int [] nums ) {
9096 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+ }
101108 }
109+ ans += left - j - 1 ;
102110 }
103111 }
104- return res ;
112+ return ans ;
105113 }
106114}
107115```
@@ -112,12 +120,14 @@ class Solution {
112120class Solution {
113121public:
114122 int triangleNumber(vector<int >& nums) {
115- sort(nums.begin(), nums.end() );
123+ ranges:: sort(nums);
116124 int ans = 0, n = nums.size();
117125 for (int i = 0; i < n - 2; ++i) {
118126 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);
121131 }
122132 }
123133 return ans;
@@ -130,19 +140,15 @@ public:
130140```go
131141func triangleNumber(nums []int) int {
132142 sort.Ints(nums)
143+ n := len(nums)
133144 ans := 0
134- for i, n := 0, len(nums) ; i < n-2; i++ {
145+ for i := 0; i < n-2; i++ {
135146 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
144151 }
145- ans += left - j - 1
146152 }
147153 }
148154 return ans
@@ -154,17 +160,14 @@ func triangleNumber(nums []int) int {
154160``` ts
155161function triangleNumber(nums : number []): number {
156162 nums .sort ((a , b ) => a - b );
157- let n = nums .length ;
163+ const n = nums .length ;
158164 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 ;
168171 }
169172 }
170173 }
@@ -179,56 +182,26 @@ impl Solution {
179182 pub fn triangle_number (mut nums : Vec <i32 >) -> i32 {
180183 nums . sort ();
181184 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 {
225194 left = mid + 1 ;
195+ } else {
196+ right = mid ;
226197 }
227198 }
228- ans += left - j - 1 ;
199+ if left > j + 1 {
200+ ans += (left - 1 - j ) as i32 ;
201+ }
229202 }
230203 }
231- return ans;
204+ ans
232205 }
233206}
234207```
0 commit comments