LC 1769. 移动所有球到每个盒子所需的最小操作数

题目描述

这是 LeetCode 上的 1769. 移动所有球到每个盒子所需的最小操作数 ,难度为 中等

n 个盒子。给你一个长度为 n 的二进制字符串 boxes,其中 boxes[i] 的值为 '0' 表示第 i 个盒子是 空 的,而 boxes[i] 的值为 '1' 表示盒子里有 一个 小球。

在一步操作中,你可以将 一个 小球从某个盒子移动到一个与之相邻的盒子中。第 i 个盒子和第 j 个盒子相邻需满足 abs(i - j) == 1。注意,操作执行后,某些盒子中可能会存在不止一个小球。

返回一个长度为 n 的数组 answer,其中 answer[i] 是将所有小球移动到第 i 个盒子所需的 最小 操作数。

每个 answer[i] 都需要根据盒子的 初始状态 进行计算。

示例 1:

1
2
3
4
5
6
7
8
输入:boxes = "110"

输出:[1,1,3]

解释:每个盒子对应的最小操作数如下:
1) 第 1 个盒子:将一个小球从第 2 个盒子移动到第 1 个盒子,需要 1 步操作。
2) 第 2 个盒子:将一个小球从第 1 个盒子移动到第 2 个盒子,需要 1 步操作。
3) 第 3 个盒子:将一个小球从第 1 个盒子移动到第 3 个盒子,需要 2 步操作。将一个小球从第 2 个盒子移动到第 3 个盒子,需要 1 步操作。共计 3 步操作。

示例 2:
1
2
3
输入:boxes = "001011"

输出:[11,8,5,4,3,4]

提示:

  • $n = boxes.length$
  • $1 <= n <= 2000$
  • boxes[i]'0''1'

模拟

预处理两个与 boxes 等长的数组 lr:$l[i]$ 和 $r[i]$ 分别代表「将 $[0, i]$ 的小球移动到位置 $i$」以及「将 $[i, n - 1]$ 的小球移动到位置 $i$」所需要的步数。

所求的答案数组 ans 与数组 lr 的关系为:$ans[i] = l[i] + r[i]$。

预处理两数组是简单的:分别从两个方向遍历 boxes,使用变量 cur 代表当前处理到的前缀/后缀的小球总个数,变量 step 代表将当前所有前缀/后缀小球移动到位置 $i$ 所需要的步数。

Java 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int[] minOperations(String boxes) {
int n = boxes.length();
int[] l = new int[n + 10], r = new int[n + 10];
for (int i = 0, cur = 0, step = 0; i < n; i++) {
step += cur; cur += boxes.charAt(i) - '0'; l[i] = step;
}
for (int i = n - 1, cur = 0, step = 0; i >= 0; i--) {
step += cur; cur += boxes.charAt(i) - '0'; r[i] = step;
}
int[] ans = new int[n];
for (int i = 0; i < n; i++) ans[i] = l[i] + r[i];
return ans;
}
}

TypeScript 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
function minOperations(boxes: string): number[] {
const n = boxes.length
const l = new Array<number>(n + 10).fill(0), r = new Array<number>(n + 10).fill(0)
for (let i = 0, cur = 0, step = 0; i < n; i++) {
step += cur; cur += boxes[i] == '1' ? 1 : 0; l[i] = step;
}
for (let i = n - 1, cur = 0, step = 0; i >= 0; i--) {
step += cur; cur += boxes[i] == '1' ? 1 : 0; r[i] = step;
}
const ans = new Array<number>(n).fill(0)
for (let i = 0; i < n; i++) ans[i] = l[i] + r[i]
return ans
}

Python 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def minOperations(self, boxes: str) -> List[int]:
n = len(boxes)
l, r = [0] * n, [0] * n
step, cur = 0, 0
for i in range(n):
step, cur = step + cur, cur + 1 if boxes[i] == '1' else cur
l[i] = step
step, cur = 0, 0
for i in range(n - 1, -1, -1):
step, cur = step + cur, cur + 1 if boxes[i] == '1' else cur
r[i] = step
return [l[i] + r[i] for i in range(n)]

  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$

最后

这是我们「刷穿 LeetCode」系列文章的第 No.1769 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!