|
| 1 | +--- |
| 2 | +title: 1552.两球之间的磁力:二分查找 |
| 3 | +date: 2025-02-14 11:07:39 |
| 4 | +tags: [题解, LeetCode, 中等, 数组, 二分查找, 二分, 排序] |
| 5 | +--- |
| 6 | + |
| 7 | +# 【LetMeFly】1552.两球之间的磁力:二分查找 |
| 8 | + |
| 9 | +力扣题目链接:[https://leetcode.cn/problems/magnetic-force-between-two-balls/](https://leetcode.cn/problems/magnetic-force-between-two-balls/) |
| 10 | + |
| 11 | +<p>在代号为 C-137 的地球上,Rick 发现如果他将两个球放在他新发明的篮子里,它们之间会形成特殊形式的磁力。Rick 有 <code>n</code> 个空的篮子,第 <code>i</code> 个篮子的位置在 <code>position[i]</code> ,Morty 想把 <code>m</code> 个球放到这些篮子里,使得任意两球间 <strong>最小磁力</strong> 最大。</p> |
| 12 | + |
| 13 | +<p>已知两个球如果分别位于 <code>x</code> 和 <code>y</code> ,那么它们之间的磁力为 <code>|x - y|</code> 。</p> |
| 14 | + |
| 15 | +<p>给你一个整数数组 <code>position</code> 和一个整数 <code>m</code> ,请你返回最大化的最小磁力。</p> |
| 16 | + |
| 17 | +<p> </p> |
| 18 | + |
| 19 | +<p><strong>示例 1:</strong></p> |
| 20 | + |
| 21 | +<p><img alt="" src="https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/08/16/q3v1.jpg" style="height: 195px; width: 562px;"></p> |
| 22 | + |
| 23 | +<pre><strong>输入:</strong>position = [1,2,3,4,7], m = 3 |
| 24 | +<strong>输出:</strong>3 |
| 25 | +<strong>解释:</strong>将 3 个球分别放入位于 1,4 和 7 的三个篮子,两球间的磁力分别为 [3, 3, 6]。最小磁力为 3 。我们没办法让最小磁力大于 3 。 |
| 26 | +</pre> |
| 27 | + |
| 28 | +<p><strong>示例 2:</strong></p> |
| 29 | + |
| 30 | +<pre><strong>输入:</strong>position = [5,4,3,2,1,1000000000], m = 2 |
| 31 | +<strong>输出:</strong>999999999 |
| 32 | +<strong>解释:</strong>我们使用位于 1 和 1000000000 的篮子时最小磁力最大。 |
| 33 | +</pre> |
| 34 | + |
| 35 | +<p> </p> |
| 36 | + |
| 37 | +<p><strong>提示:</strong></p> |
| 38 | + |
| 39 | +<ul> |
| 40 | + <li><code>n == position.length</code></li> |
| 41 | + <li><code>2 <= n <= 10^5</code></li> |
| 42 | + <li><code>1 <= position[i] <= 10^9</code></li> |
| 43 | + <li>所有 <code>position</code> 中的整数 <strong>互不相同</strong> 。</li> |
| 44 | + <li><code>2 <= m <= position.length</code></li> |
| 45 | +</ul> |
| 46 | + |
| 47 | + |
| 48 | + |
| 49 | +## 解题方法:二分查找 |
| 50 | + |
| 51 | +能做到“最小磁力”为$a$的话,更容易做到“最小磁力”为$a-1$。这就很适合二分。 |
| 52 | + |
| 53 | +闭区间二分,初始范围`[1, max(position) - min(position)]`。 |
| 54 | + |
| 55 | +每次令$mid = \lceil\frac{l+r}2\rceil$,若$mid$可行就令$l=mid$,否则就令$r=mid-1$。 |
| 56 | + |
| 57 | +最终返回$l$即为答案。 |
| 58 | + |
| 59 | ++ 时间复杂度$O(n\log n)$ |
| 60 | ++ 空间复杂度$O(\log n)$ |
| 61 | + |
| 62 | +### AC代码 |
| 63 | + |
| 64 | +#### C++ |
| 65 | + |
| 66 | +```cpp |
| 67 | +/* |
| 68 | + * @Author: LetMeFly |
| 69 | + * @Date: 2025-02-14 10:45:38 |
| 70 | + * @LastEditors: LetMeFly.xyz |
| 71 | + * @LastEditTime: 2025-02-14 10:55:39 |
| 72 | + */ |
| 73 | +class Solution { |
| 74 | +private: |
| 75 | + bool check(vector<int>& v, int m, int d) { |
| 76 | + int lastPosition = -1000000000; |
| 77 | + for (int t : v) { |
| 78 | + if (t - lastPosition >= d) { |
| 79 | + m--; |
| 80 | + if (!m) { |
| 81 | + return true; |
| 82 | + } |
| 83 | + lastPosition = t; |
| 84 | + } |
| 85 | + } |
| 86 | + return false; |
| 87 | + } |
| 88 | +public: |
| 89 | + int maxDistance(vector<int>& position, int m) { |
| 90 | + sort(position.begin(), position.end()); |
| 91 | + int l = 1, r = position.back() - position[0]; |
| 92 | + while (l < r) { |
| 93 | + int mid = (l + r + 1) >> 1; |
| 94 | + if (check(position, m, mid)) { |
| 95 | + l = mid; |
| 96 | + } else { |
| 97 | + r = mid - 1; |
| 98 | + } |
| 99 | + } |
| 100 | + return l; |
| 101 | + } |
| 102 | +}; |
| 103 | +``` |
| 104 | +
|
| 105 | +#### Python |
| 106 | +
|
| 107 | +```python |
| 108 | +''' |
| 109 | +Author: LetMeFly |
| 110 | +Date: 2025-02-14 10:56:04 |
| 111 | +LastEditors: LetMeFly.xyz |
| 112 | +LastEditTime: 2025-02-14 10:58:23 |
| 113 | +''' |
| 114 | +from typing import List |
| 115 | +
|
| 116 | +class Solution: |
| 117 | + def check(self, m: int, d: int) -> bool: |
| 118 | + last = -1000000000 |
| 119 | + for t in self.position: |
| 120 | + if t - last >= d: |
| 121 | + m -= 1 |
| 122 | + if not m: |
| 123 | + return True |
| 124 | + last = t |
| 125 | + return False |
| 126 | + |
| 127 | + def maxDistance(self, position: List[int], m: int) -> int: |
| 128 | + position.sort() |
| 129 | + self.position = position |
| 130 | + l, r = 1, position[-1] - position[0] |
| 131 | + while l < r: |
| 132 | + mid = (l + r + 1) >> 1 |
| 133 | + if self.check(m, mid): |
| 134 | + l = mid |
| 135 | + else: |
| 136 | + r = mid - 1 |
| 137 | + return l |
| 138 | +``` |
| 139 | + |
| 140 | +#### Java |
| 141 | + |
| 142 | +```java |
| 143 | +/* |
| 144 | + * @Author: LetMeFly |
| 145 | + * @Date: 2025-02-14 10:56:24 |
| 146 | + * @LastEditors: LetMeFly.xyz |
| 147 | + * @LastEditTime: 2025-02-14 11:02:35 |
| 148 | + */ |
| 149 | +import java.util.Arrays; |
| 150 | + |
| 151 | + |
| 152 | +class Solution { |
| 153 | + private int[] v; |
| 154 | + |
| 155 | + private boolean check(int m, int d) { |
| 156 | + int last = -1000000000; |
| 157 | + for (int t : v) { |
| 158 | + if (t - last >= d) { |
| 159 | + if (--m == 0) { |
| 160 | + return true; |
| 161 | + } |
| 162 | + last = t; |
| 163 | + } |
| 164 | + } |
| 165 | + return false; |
| 166 | + } |
| 167 | + |
| 168 | + public int maxDistance(int[] position, int m) { |
| 169 | + Arrays.sort(position); |
| 170 | + v = position; |
| 171 | + int l = 1, r = v[v.length - 1] - v[0]; |
| 172 | + while (l < r) { |
| 173 | + int mid = (l + r + 1) >> 1; |
| 174 | + if (check(m, mid)) { |
| 175 | + l = mid; |
| 176 | + } else { |
| 177 | + r = mid - 1; |
| 178 | + } |
| 179 | + } |
| 180 | + return l; |
| 181 | + } |
| 182 | +} |
| 183 | +``` |
| 184 | + |
| 185 | +#### Go |
| 186 | + |
| 187 | +```go |
| 188 | +/* |
| 189 | + * @Author: LetMeFly |
| 190 | + * @Date: 2025-02-14 10:56:28 |
| 191 | + * @LastEditors: LetMeFly.xyz |
| 192 | + * @LastEditTime: 2025-02-14 11:05:50 |
| 193 | + */ |
| 194 | +package main |
| 195 | + |
| 196 | +import "slices" |
| 197 | + |
| 198 | +func check_MFB2B(v []int, m, d int) bool { |
| 199 | + last := -1000000000 |
| 200 | + for _, t := range v { |
| 201 | + if t - last >= d { |
| 202 | + m-- |
| 203 | + if m <= 0 { |
| 204 | + return true |
| 205 | + } |
| 206 | + last = t |
| 207 | + } |
| 208 | + } |
| 209 | + return false |
| 210 | +} |
| 211 | + |
| 212 | +func maxDistance(position []int, m int) int { |
| 213 | + slices.Sort(position) |
| 214 | + l, r := 1, position[len(position) - 1] - position[0] |
| 215 | + for l < r { |
| 216 | + mid := (l + r + 1) >> 1 |
| 217 | + if check_MFB2B(position, m, mid) { |
| 218 | + l = mid |
| 219 | + } else { |
| 220 | + r = mid - 1 |
| 221 | + } |
| 222 | + } |
| 223 | + return l |
| 224 | +} |
| 225 | +``` |
| 226 | + |
| 227 | +> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/145629037)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/02/14/LeetCode%201552.%E4%B8%A4%E7%90%83%E4%B9%8B%E9%97%B4%E7%9A%84%E7%A3%81%E5%8A%9B/)哦~ |
| 228 | +> |
| 229 | +> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode) |
| 230 | +> |
| 231 | +> Tisfy:[https://blog.letmefly.xyz/2025/02/14/LeetCode 1552.两球之间的磁力/](https://blog.letmefly.xyz/2025/02/14/LeetCode%201552.%E4%B8%A4%E7%90%83%E4%B9%8B%E9%97%B4%E7%9A%84%E7%A3%81%E5%8A%9B/) |
0 commit comments