Skip to content

Commit b0caffd

Browse files
authored
feat: add solutions to lc problem: No.1552 (#3143)
No.1552.Magnetic Force Between Two Balls
1 parent 76e854a commit b0caffd

File tree

9 files changed

+278
-241
lines changed

9 files changed

+278
-241
lines changed

solution/1500-1599/1552.Magnetic Force Between Two Balls/README.md

Lines changed: 95 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,13 @@ tags:
6464

6565
### 方法一:二分查找
6666

67-
先对 position 进行排序
67+
我们注意到,任意两球间的最小磁力越大,能够放入的球的数量就越少,这存在着单调性。我们可以使用二分查找,找到最大的最小磁力,使得能够放入的球的数量不小于 $m$
6868

69-
然后二分枚举磁力值(相邻两球的最小间距),统计当前最小磁力值下能放下多少个小球,记为 cnt。若 `cnt >= m`,说明此磁力值符合条件。继续二分查找,最终找到符合条件的最大磁力值。
69+
我们首先对篮子的位置进行排序,然后使用二分查找的方法,定义二分查找的左边界 $l = 1$,右边界 $r = \text{position}[n - 1]$,其中 $n$ 为篮子的数量。在每次二分查找的过程中,我们计算取中值 $m = (l + r + 1) / 2$,然后判断是否存在一种放置球的方法,使得能够放入的球的数量不小于 $m$。
70+
71+
问题转换为判断一个给定的最小磁力 $f$ 是否能够放入 $m$ 个球。我们可以从左到右遍历篮子的位置,如果上一个球的位置与当前篮子的位置的距离大于等于 $f$,则说明可以在当前篮子放置一个球。最后判断放置的球的数量是否不小于 $m$ 即可。
72+
73+
时间复杂度 $O(n \times \log n + n \times \log M)$,空间复杂度 $O(\log n)$。其中 $n$ 和 $M$ 分别为篮子的数量和篮子的位置的最大值。
7074

7175
<!-- tabs:start -->
7276

@@ -75,56 +79,51 @@ tags:
7579
```python
7680
class Solution:
7781
def maxDistance(self, position: List[int], m: int) -> int:
78-
def check(f):
79-
prev = position[0]
80-
cnt = 1
81-
for curr in position[1:]:
82+
def check(f: int) -> bool:
83+
prev = -inf
84+
cnt = 0
85+
for curr in position:
8286
if curr - prev >= f:
8387
prev = curr
8488
cnt += 1
85-
return cnt >= m
89+
return cnt < m
8690

8791
position.sort()
88-
left, right = 1, position[-1]
89-
while left < right:
90-
mid = (left + right + 1) >> 1
91-
92-
if check(mid):
93-
left = mid
94-
else:
95-
right = mid - 1
96-
return left
92+
l, r = 1, position[-1]
93+
return bisect_left(range(l, r + 1), True, key=check)
9794
```
9895

9996
#### Java
10097

10198
```java
10299
class Solution {
100+
private int[] position;
101+
103102
public int maxDistance(int[] position, int m) {
104103
Arrays.sort(position);
105-
int left = 1, right = position[position.length - 1];
106-
while (left < right) {
107-
int mid = (left + right + 1) >>> 1;
108-
if (check(position, mid, m)) {
109-
left = mid;
104+
this.position = position;
105+
int l = 1, r = position[position.length - 1];
106+
while (l < r) {
107+
int mid = (l + r + 1) >> 1;
108+
if (count(mid) >= m) {
109+
l = mid;
110110
} else {
111-
right = mid - 1;
111+
r = mid - 1;
112112
}
113113
}
114-
return left;
114+
return l;
115115
}
116116

117-
private boolean check(int[] position, int f, int m) {
117+
private int count(int f) {
118118
int prev = position[0];
119119
int cnt = 1;
120-
for (int i = 1; i < position.length; ++i) {
121-
int curr = position[i];
120+
for (int curr : position) {
122121
if (curr - prev >= f) {
123-
prev = curr;
124122
++cnt;
123+
prev = curr;
125124
}
126125
}
127-
return cnt >= m;
126+
return cnt;
128127
}
129128
}
130129
```
@@ -136,28 +135,27 @@ class Solution {
136135
public:
137136
int maxDistance(vector<int>& position, int m) {
138137
sort(position.begin(), position.end());
139-
int left = 1, right = position[position.size() - 1];
140-
while (left < right) {
141-
int mid = (left + right + 1) >> 1;
142-
if (check(position, mid, m))
143-
left = mid;
144-
else
145-
right = mid - 1;
146-
}
147-
return left;
148-
}
149-
150-
bool check(vector<int>& position, int f, int m) {
151-
int prev = position[0];
152-
int cnt = 1;
153-
for (int i = 1; i < position.size(); ++i) {
154-
int curr = position[i];
155-
if (curr - prev >= f) {
156-
prev = curr;
157-
++cnt;
138+
int l = 1, r = position.back();
139+
auto count = [&](int f) {
140+
int prev = position[0];
141+
int cnt = 1;
142+
for (int& curr : position) {
143+
if (curr - prev >= f) {
144+
prev = curr;
145+
cnt++;
146+
}
147+
}
148+
return cnt;
149+
};
150+
while (l < r) {
151+
int mid = (l + r + 1) >> 1;
152+
if (count(mid) >= m) {
153+
l = mid;
154+
} else {
155+
r = mid - 1;
158156
}
159157
}
160-
return cnt >= m;
158+
return l;
161159
}
162160
};
163161
```
@@ -167,26 +165,46 @@ public:
167165
```go
168166
func maxDistance(position []int, m int) int {
169167
sort.Ints(position)
170-
left, right := 1, position[len(position)-1]
171-
check := func(f int) bool {
172-
prev, cnt := position[0], 1
173-
for _, curr := range position[1:] {
168+
return sort.Search(position[len(position)-1], func(f int) bool {
169+
prev := position[0]
170+
cnt := 1
171+
for _, curr := range position {
174172
if curr-prev >= f {
175-
prev = curr
176173
cnt++
174+
prev = curr
177175
}
178176
}
179-
return cnt >= m
180-
}
181-
for left < right {
182-
mid := (left + right + 1) >> 1
183-
if check(mid) {
184-
left = mid
185-
} else {
186-
right = mid - 1
187-
}
188-
}
189-
return left
177+
return cnt < m
178+
}) - 1
179+
}
180+
```
181+
182+
#### TypeScript
183+
184+
```ts
185+
function maxDistance(position: number[], m: number): number {
186+
position.sort((a, b) => a - b);
187+
let [l, r] = [1, position.at(-1)!];
188+
const count = (f: number): number => {
189+
let cnt = 1;
190+
let prev = position[0];
191+
for (const curr of position) {
192+
if (curr - prev >= f) {
193+
cnt++;
194+
prev = curr;
195+
}
196+
}
197+
return cnt;
198+
};
199+
while (l < r) {
200+
const mid = (l + r + 1) >> 1;
201+
if (count(mid) >= m) {
202+
l = mid;
203+
} else {
204+
r = mid - 1;
205+
}
206+
}
207+
return l;
190208
}
191209
```
192210

@@ -199,32 +217,28 @@ func maxDistance(position []int, m int) int {
199217
* @return {number}
200218
*/
201219
var maxDistance = function (position, m) {
202-
position.sort((a, b) => {
203-
return a - b;
204-
});
205-
let left = 1,
206-
right = position[position.length - 1];
207-
const check = function (f) {
208-
let prev = position[0];
220+
position.sort((a, b) => a - b);
221+
let [l, r] = [1, position.at(-1)];
222+
const count = f => {
209223
let cnt = 1;
210-
for (let i = 1; i < position.length; ++i) {
211-
const curr = position[i];
224+
let prev = position[0];
225+
for (const curr of position) {
212226
if (curr - prev >= f) {
227+
cnt++;
213228
prev = curr;
214-
++cnt;
215229
}
216230
}
217-
return cnt >= m;
231+
return cnt;
218232
};
219-
while (left < right) {
220-
const mid = (left + right + 1) >> 1;
221-
if (check(mid)) {
222-
left = mid;
233+
while (l < r) {
234+
const mid = (l + r + 1) >> 1;
235+
if (count(mid) >= m) {
236+
l = mid;
223237
} else {
224-
right = mid - 1;
238+
r = mid - 1;
225239
}
226240
}
227-
return left;
241+
return l;
228242
};
229243
```
230244

0 commit comments

Comments
 (0)