Skip to content

Commit d50c095

Browse files
authored
feat: add solutions to lc problem: No.3086 (doocs#3199)
No.3086.Minimum Moves to Pick K Ones
1 parent f2a4791 commit d50c095

File tree

7 files changed

+787
-8
lines changed

7 files changed

+787
-8
lines changed

solution/3000-3099/3086.Minimum Moves to Pick K Ones/README.md

Lines changed: 267 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,32 +88,295 @@ tags:
8888

8989
<!-- solution:start -->
9090

91-
### 方法一
91+
### 方法一:贪心 + 前缀和 + 二分查找
92+
93+
我们考虑枚举 Alice 的站立位置 $i$,对于每个 $i$,我们按照如下的策略进行操作:
94+
95+
- 首先,如果位置 $i$ 的数字为 $1$,我们可以直接拾取一个 $1$,不需要行动次数。
96+
- 然后,我们对 $i$ 的左右两侧位置的数字 $1$ 进行拾取,执行的是行动 $2$,即把位置 $i-1$ 的 $1$ 移到位置 $i$,然后拾取;把位置 $i+1$ 的 $1$ 移到位置 $i$,然后拾取。每拾取一个 $1$,需要 $1$ 次行动。
97+
- 接下来,我们最大限度地将 $i-1$ 或 $i+1$ 上的 $0$,利用行动 $1$,将其置为 $1$,然后利用行动 $2$,将其移动到位置 $i$,拾取。直到拾取的 $1$ 的数量达到 $k$ 或者行动 $1$ 的次数达到 $\text{maxChanges}$。我们假设行动 $1$ 的次数为 $c$,那么总共需要 $2c$ 次行动。
98+
- 利用完行动 $1$,如果拾取的 $1$ 的数量还没有达到 $k$,我们需要继续考虑在 $[1,..i-2]$ 和 $[i+2,..n]$ 的区间内,进行行动 $2$,将 $1$ 移动到位置 $i$,拾取。我们可以使用二分查找来确定这个区间的大小,使得拾取的 $1$ 的数量达到 $k$。具体地,我们二分枚举一个区间的大小 $d$,然后在区间 $[i-d,..i-2]$ 和 $[i+2,..i+d]$ 内,进行行动 $2$,将 $1$ 移动到位置 $i$,拾取。如果拾取的 $1$ 的数量达到 $k$,我们就更新答案。
99+
100+
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\text{nums}$ 的长度。
92101

93102
<!-- tabs:start -->
94103

95104
#### Python3
96105

97106
```python
98-
107+
class Solution:
108+
def minimumMoves(self, nums: List[int], k: int, maxChanges: int) -> int:
109+
n = len(nums)
110+
cnt = [0] * (n + 1)
111+
s = [0] * (n + 1)
112+
for i, x in enumerate(nums, 1):
113+
cnt[i] = cnt[i - 1] + x
114+
s[i] = s[i - 1] + i * x
115+
ans = inf
116+
max = lambda x, y: x if x > y else y
117+
min = lambda x, y: x if x < y else y
118+
for i, x in enumerate(nums, 1):
119+
t = 0
120+
need = k - x
121+
for j in (i - 1, i + 1):
122+
if need > 0 and 1 <= j <= n and nums[j - 1] == 1:
123+
need -= 1
124+
t += 1
125+
c = min(need, maxChanges)
126+
need -= c
127+
t += c * 2
128+
if need <= 0:
129+
ans = min(ans, t)
130+
continue
131+
l, r = 2, max(i - 1, n - i)
132+
while l <= r:
133+
mid = (l + r) >> 1
134+
l1, r1 = max(1, i - mid), max(0, i - 2)
135+
l2, r2 = min(n + 1, i + 2), min(n, i + mid)
136+
c1 = cnt[r1] - cnt[l1 - 1]
137+
c2 = cnt[r2] - cnt[l2 - 1]
138+
if c1 + c2 >= need:
139+
t1 = c1 * i - (s[r1] - s[l1 - 1])
140+
t2 = s[r2] - s[l2 - 1] - c2 * i
141+
ans = min(ans, t + t1 + t2)
142+
r = mid - 1
143+
else:
144+
l = mid + 1
145+
return ans
99146
```
100147

101148
#### Java
102149

103150
```java
104-
151+
class Solution {
152+
public long minimumMoves(int[] nums, int k, int maxChanges) {
153+
int n = nums.length;
154+
int[] cnt = new int[n + 1];
155+
long[] s = new long[n + 1];
156+
for (int i = 1; i <= n; ++i) {
157+
cnt[i] = cnt[i - 1] + nums[i - 1];
158+
s[i] = s[i - 1] + i * nums[i - 1];
159+
}
160+
long ans = Long.MAX_VALUE;
161+
for (int i = 1; i <= n; ++i) {
162+
long t = 0;
163+
int need = k - nums[i - 1];
164+
for (int j = i - 1; j <= i + 1; j += 2) {
165+
if (need > 0 && 1 <= j && j <= n && nums[j - 1] == 1) {
166+
--need;
167+
++t;
168+
}
169+
}
170+
int c = Math.min(need, maxChanges);
171+
need -= c;
172+
t += c * 2;
173+
if (need <= 0) {
174+
ans = Math.min(ans, t);
175+
continue;
176+
}
177+
int l = 2, r = Math.max(i - 1, n - i);
178+
while (l <= r) {
179+
int mid = (l + r) >> 1;
180+
int l1 = Math.max(1, i - mid), r1 = Math.max(0, i - 2);
181+
int l2 = Math.min(n + 1, i + 2), r2 = Math.min(n, i + mid);
182+
int c1 = cnt[r1] - cnt[l1 - 1];
183+
int c2 = cnt[r2] - cnt[l2 - 1];
184+
if (c1 + c2 >= need) {
185+
long t1 = 1L * c1 * i - (s[r1] - s[l1 - 1]);
186+
long t2 = s[r2] - s[l2 - 1] - 1L * c2 * i;
187+
ans = Math.min(ans, t + t1 + t2);
188+
r = mid - 1;
189+
} else {
190+
l = mid + 1;
191+
}
192+
}
193+
}
194+
return ans;
195+
}
196+
}
105197
```
106198

107199
#### C++
108200

109201
```cpp
110-
202+
class Solution {
203+
public:
204+
long long minimumMoves(vector<int>& nums, int k, int maxChanges) {
205+
int n = nums.size();
206+
vector<int> cnt(n + 1, 0);
207+
vector<long long> s(n + 1, 0);
208+
209+
for (int i = 1; i <= n; ++i) {
210+
cnt[i] = cnt[i - 1] + nums[i - 1];
211+
s[i] = s[i - 1] + 1LL * i * nums[i - 1];
212+
}
213+
214+
long long ans = LLONG_MAX;
215+
216+
for (int i = 1; i <= n; ++i) {
217+
long long t = 0;
218+
int need = k - nums[i - 1];
219+
220+
for (int j = i - 1; j <= i + 1; j += 2) {
221+
if (need > 0 && 1 <= j && j <= n && nums[j - 1] == 1) {
222+
--need;
223+
++t;
224+
}
225+
}
226+
227+
int c = min(need, maxChanges);
228+
need -= c;
229+
t += c * 2;
230+
231+
if (need <= 0) {
232+
ans = min(ans, t);
233+
continue;
234+
}
235+
236+
int l = 2, r = max(i - 1, n - i);
237+
238+
while (l <= r) {
239+
int mid = (l + r) / 2;
240+
int l1 = max(1, i - mid), r1 = max(0, i - 2);
241+
int l2 = min(n + 1, i + 2), r2 = min(n, i + mid);
242+
243+
int c1 = cnt[r1] - cnt[l1 - 1];
244+
int c2 = cnt[r2] - cnt[l2 - 1];
245+
246+
if (c1 + c2 >= need) {
247+
long long t1 = 1LL * c1 * i - (s[r1] - s[l1 - 1]);
248+
long long t2 = s[r2] - s[l2 - 1] - 1LL * c2 * i;
249+
ans = min(ans, t + t1 + t2);
250+
r = mid - 1;
251+
} else {
252+
l = mid + 1;
253+
}
254+
}
255+
}
256+
257+
return ans;
258+
}
259+
};
111260
```
112261

113262
#### Go
114263

115264
```go
265+
func minimumMoves(nums []int, k int, maxChanges int) int64 {
266+
n := len(nums)
267+
cnt := make([]int, n+1)
268+
s := make([]int, n+1)
269+
270+
for i := 1; i <= n; i++ {
271+
cnt[i] = cnt[i-1] + nums[i-1]
272+
s[i] = s[i-1] + i*nums[i-1]
273+
}
274+
275+
ans := math.MaxInt64
276+
277+
for i := 1; i <= n; i++ {
278+
t := 0
279+
need := k - nums[i-1]
280+
281+
for _, j := range []int{i - 1, i + 1} {
282+
if need > 0 && 1 <= j && j <= n && nums[j-1] == 1 {
283+
need--
284+
t++
285+
}
286+
}
287+
288+
c := min(need, maxChanges)
289+
need -= c
290+
t += c * 2
291+
292+
if need <= 0 {
293+
ans = min(ans, t)
294+
continue
295+
}
296+
297+
l, r := 2, max(i-1, n-i)
298+
299+
for l <= r {
300+
mid := (l + r) >> 1
301+
l1, r1 := max(1, i-mid), max(0, i-2)
302+
l2, r2 := min(n+1, i+2), min(n, i+mid)
303+
304+
c1 := cnt[r1] - cnt[l1-1]
305+
c2 := cnt[r2] - cnt[l2-1]
306+
307+
if c1+c2 >= need {
308+
t1 := c1*i - (s[r1] - s[l1-1])
309+
t2 := s[r2] - s[l2-1] - c2*i
310+
ans = min(ans, t+t1+t2)
311+
r = mid - 1
312+
} else {
313+
l = mid + 1
314+
}
315+
}
316+
}
317+
318+
return int64(ans)
319+
}
320+
```
116321

322+
#### TypeScript
323+
324+
```ts
325+
function minimumMoves(nums: number[], k: number, maxChanges: number): number {
326+
const n = nums.length;
327+
const cnt = Array(n + 1).fill(0);
328+
const s = Array(n + 1).fill(0);
329+
330+
for (let i = 1; i <= n; i++) {
331+
cnt[i] = cnt[i - 1] + nums[i - 1];
332+
s[i] = s[i - 1] + i * nums[i - 1];
333+
}
334+
335+
let ans = Infinity;
336+
for (let i = 1; i <= n; i++) {
337+
let t = 0;
338+
let need = k - nums[i - 1];
339+
340+
for (let j of [i - 1, i + 1]) {
341+
if (need > 0 && 1 <= j && j <= n && nums[j - 1] === 1) {
342+
need--;
343+
t++;
344+
}
345+
}
346+
347+
const c = Math.min(need, maxChanges);
348+
need -= c;
349+
t += c * 2;
350+
351+
if (need <= 0) {
352+
ans = Math.min(ans, t);
353+
continue;
354+
}
355+
356+
let l = 2,
357+
r = Math.max(i - 1, n - i);
358+
359+
while (l <= r) {
360+
const mid = (l + r) >> 1;
361+
const [l1, r1] = [Math.max(1, i - mid), Math.max(0, i - 2)];
362+
const [l2, r2] = [Math.min(n + 1, i + 2), Math.min(n, i + mid)];
363+
364+
const c1 = cnt[r1] - cnt[l1 - 1];
365+
const c2 = cnt[r2] - cnt[l2 - 1];
366+
367+
if (c1 + c2 >= need) {
368+
const t1 = c1 * i - (s[r1] - s[l1 - 1]);
369+
const t2 = s[r2] - s[l2 - 1] - c2 * i;
370+
ans = Math.min(ans, t + t1 + t2);
371+
r = mid - 1;
372+
} else {
373+
l = mid + 1;
374+
}
375+
}
376+
}
377+
378+
return ans;
379+
}
117380
```
118381

119382
<!-- tabs:end -->

0 commit comments

Comments
 (0)