56
56
57
57
<!-- 这里可写通用的实现逻辑 -->
58
58
59
- ** 方法一:二分查找**
59
+ ** 方法一:贪心 + 二分查找**
60
60
61
- 我们先对数组 ` price ` 进行排序,然后二分枚举甜蜜度,找到最大的且满足至少有 $k$ 类糖果的甜蜜度 。
61
+ 我们注意到,如果一个甜蜜度为 $x$ 的礼盒是可行的,那么所有甜蜜度小于 $x$ 的礼盒也是可行的,这存在单调性,因此可以使用二分查找的方法找到最大的可行甜蜜度 。
62
62
63
- 时间复杂度 $O(n \times \log M)$,空间复杂度 $O(1)$。其中 $n$ 为数组 ` price ` 的长度,而 $M$ 为数组 ` price ` 中的最大值。本题中我们取 $M = 10^9$。
63
+ 我们首先将数组 $price$ 排序,然后定义二分查找的左边界 $l=0$, $r=price[ n-1] -price[ 0] $。每一次,我们计算出当前的中间值 $mid = \lfloor \frac{l+r+1}{2} \rfloor$,以 $mid$ 作为甜蜜度,判断是否可行。若可行,那么我们将左边界 $l$ 更新为 $mid$,否则将右边界 $r$ 更新为 $mid-1$。最后返回 $l$ 即可。
64
+
65
+ 那么问题的关键就是判断一个甜蜜度是否可行,我们通过函数 $check(x)$ 来判断。函数 $check(x)$ 的实现逻辑如下:
66
+
67
+ 定义一个变量 $cnt$ 表示当前已经选取的糖果的数量,初始值为 $0$,定义一个变量 $pre$ 表示上一个选取的糖果的价格,初始值为 $-x$。然后我们遍历排好序的数组 $price$,对于每一个糖果的价格 $cur$,如果 $cur-pre \geq x$,那么我们就选取这个糖果,将 $pre$ 更新为 $cur$,并将 $cnt$ 加一。最后判断 $cnt$ 是否大于等于 $k$,如果是,那么返回 $true$,否则返回 $false$。
68
+
69
+ 时间复杂度 $O(n \times (\log n + \log M))$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 $price$ 的长度;而 $M$ 是数组 $price$ 中的最大值,本题中 $M \leq 10^9$。
64
70
65
71
<!-- tabs:start -->
66
72
71
77
``` python
72
78
class Solution :
73
79
def maximumTastiness (self , price : List[int ], k : int ) -> int :
74
- def check (x ):
75
- cnt = 1
76
- s = price[0 ]
77
- for p in price[1 :]:
78
- if p - s >= x:
79
- s = p
80
+ def check (x : int ) -> bool :
81
+ cnt, pre = 0 , - x
82
+ for cur in price:
83
+ if cur - pre >= x:
84
+ pre = cur
80
85
cnt += 1
81
86
return cnt >= k
82
87
83
88
price.sort()
84
- left, right = 0 , 10 ** 9
85
- while left < right :
86
- mid = (left + right + 1 ) >> 1
89
+ l, r = 0 , price[ - 1 ] - price[ 0 ]
90
+ while l < r :
91
+ mid = (l + r + 1 ) >> 1
87
92
if check(mid):
88
- left = mid
93
+ l = mid
89
94
else :
90
- right = mid - 1
91
- return left
95
+ r = mid - 1
96
+ return l
92
97
```
93
98
94
99
### ** Java**
@@ -97,31 +102,25 @@ class Solution:
97
102
98
103
``` java
99
104
class Solution {
100
- private int [] price;
101
- private int k;
102
-
103
105
public int maximumTastiness (int [] price , int k ) {
104
106
Arrays . sort(price);
105
- this . price = price;
106
- this . k = k;
107
- int left = 0 , right = 1000000000 ;
108
- while (left < right) {
109
- int mid = (left + right + 1 ) >> 1 ;
110
- if (check(mid)) {
111
- left = mid;
107
+ int l = 0 , r = price[price. length - 1 ] - price[0 ];
108
+ while (l < r) {
109
+ int mid = (l + r + 1 ) >> 1 ;
110
+ if (check(price, k, mid)) {
111
+ l = mid;
112
112
} else {
113
- right = mid - 1 ;
113
+ r = mid - 1 ;
114
114
}
115
115
}
116
- return left ;
116
+ return l ;
117
117
}
118
118
119
- private boolean check (int x ) {
120
- int s = price[0 ];
121
- int cnt = 1 ;
122
- for (int i = 1 ; i < price. length; ++ i) {
123
- if (price[i] - s >= x) {
124
- s = price[i];
119
+ private boolean check (int [] price , int k , int x ) {
120
+ int cnt = 0 , pre = - x;
121
+ for (int cur : price) {
122
+ if (cur - pre >= x) {
123
+ pre = cur;
125
124
++ cnt;
126
125
}
127
126
}
@@ -137,27 +136,26 @@ class Solution {
137
136
public:
138
137
int maximumTastiness(vector<int >& price, int k) {
139
138
sort(price.begin(), price.end());
140
- int left = 0, right = 1e9;
141
- auto check = [ &] (int x) {
142
- int s = price[ 0] ;
143
- int cnt = 1;
144
- for (int i = 1; i < price.size(); ++i) {
145
- if (price[ i] - s >= x) {
146
- s = price[ i] ;
139
+ int l = 0, r = price.back() - price[ 0] ;
140
+ auto check = [ &] (int x) -> bool {
141
+ int cnt = 0, pre = -x;
142
+ for (int& cur : price) {
143
+ if (cur - pre >= x) {
144
+ pre = cur;
147
145
++cnt;
148
146
}
149
147
}
150
148
return cnt >= k;
151
149
};
152
- while (left < right ) {
153
- int mid = (left + right + 1) >> 1;
150
+ while (l < r ) {
151
+ int mid = (l + r + 1) >> 1;
154
152
if (check(mid)) {
155
- left = mid;
153
+ l = mid;
156
154
} else {
157
- right = mid - 1;
155
+ r = mid - 1;
158
156
}
159
157
}
160
- return left ;
158
+ return l ;
161
159
}
162
160
};
163
161
```
@@ -167,27 +165,76 @@ public:
167
165
```go
168
166
func maximumTastiness(price []int, k int) int {
169
167
sort.Ints(price)
170
- check := func(x int) bool {
171
- s := price[0]
172
- cnt := 1
173
- for _, p := range price[1:] {
174
- if p-s >= x {
175
- s = p
168
+ return sort.Search(price[len(price)-1], func(x int) bool {
169
+ cnt, pre := 0, -x
170
+ for _, cur := range price {
171
+ if cur-pre >= x {
172
+ pre = cur
176
173
cnt++
177
174
}
178
175
}
179
- return cnt >= k
180
- }
181
- left, right := 0, 1000000000
182
- for left < right {
183
- mid := (left + right + 1) >> 1
184
- if check(mid) {
185
- left = mid
186
- } else {
187
- right = mid - 1
188
- }
189
- }
190
- return left
176
+ return cnt < k
177
+ }) - 1
178
+ }
179
+ ```
180
+
181
+ ### ** TypeScript**
182
+
183
+ ``` ts
184
+ function maximumTastiness(price : number [], k : number ): number {
185
+ price .sort ((a , b ) => a - b );
186
+ let l = 0 ;
187
+ let r = price [price .length - 1 ] - price [0 ];
188
+ const check = (x : number ): boolean => {
189
+ let [cnt, pre] = [0 , - x ];
190
+ for (const cur of price ) {
191
+ if (cur - pre >= x ) {
192
+ pre = cur ;
193
+ ++ cnt ;
194
+ }
195
+ }
196
+ return cnt >= k ;
197
+ };
198
+ while (l < r ) {
199
+ const mid = (l + r + 1 ) >> 1 ;
200
+ if (check (mid )) {
201
+ l = mid ;
202
+ } else {
203
+ r = mid - 1 ;
204
+ }
205
+ }
206
+ return l ;
207
+ }
208
+ ```
209
+
210
+ ### ** C#**
211
+
212
+ ``` cs
213
+ public class Solution {
214
+ public int MaximumTastiness (int [] price , int k ) {
215
+ Array .Sort (price );
216
+ int l = 0 , r = price [price .Length - 1 ] - price [0 ];
217
+ while (l < r ) {
218
+ int mid = (l + r + 1 ) >> 1 ;
219
+ if (check (price , mid , k )) {
220
+ l = mid ;
221
+ } else {
222
+ r = mid - 1 ;
223
+ }
224
+ }
225
+ return l ;
226
+ }
227
+
228
+ private bool check (int [] price , int x , int k ) {
229
+ int cnt = 0 , pre = - x ;
230
+ foreach (int cur in price ) {
231
+ if (cur - pre >= x ) {
232
+ ++ cnt ;
233
+ pre = cur ;
234
+ }
235
+ }
236
+ return cnt >= k ;
237
+ }
191
238
}
192
239
```
193
240
0 commit comments