有 n 个盒子。给你一个长度为 n 的二进制字符串 boxes ,其中 boxes[i] 的值为 '0' 表示第 i 个盒子是 空 的,而 boxes[i] 的值为 '1' 表示盒子里有 一个 小球。
在一步操作中,你可以将 一个 小球从某个盒子移动到一个与之相邻的盒子中。第 i 个盒子和第 j 个盒子相邻需满足 abs(i - j) == 1 。注意,操作执行后,某些盒子中可能会存在不止一个小球。
返回一个长度为 n 的数组 answer ,其中 answer[i] 是将所有小球移动到第 i 个盒子所需的 最小 操作数。
每个 answer[i] 都需要根据盒子的 初始状态 进行计算。
示例 1:
输入: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:
输入:boxes = "001011"
输出:[11,8,5,4,3,4]
提示:
n == boxes.length
1 <= n <= 2000
boxes[i] 为 '0' 或 '1'
对于每个位置将其他小球放置到该位置
i
i
i等于左边和右边所有的
1
1
1移动到该位置
i
i
i的总步数之和。定义
l
e
f
t
[
i
]
left[i]
left[i]代表左边所有的
1
1
1移动到位置i需要的步数,定义
c
n
t
cnt
cnt为
[
1
,
i
−
1
]
[1,i - 1]
[1,i−1]中1的个数,那么对于当前
i
i
i位置
l
e
f
t
[
i
]
=
c
n
t
+
l
e
f
t
[
i
−
1
]
left[i] = cnt + left[i - 1]
left[i]=cnt+left[i−1]。更新完
l
e
f
t
[
i
]
left[i]
left[i]后更新cnt继续遍历。同理可以定义
r
i
g
h
t
[
i
]
right[i]
right[i]代表
i
i
i右边所有的1移动到该位置花费的步数。
class Solution {
public int[] minOperations(String boxes) {
int n = boxes.length();
char[] arr = (" " + boxes).toCharArray();
int[] left = new int[n + 5], right = new int[n + 5], ans = new int[n];
int cnt1 = 0, cnt2 = 0;
for (int i = 1; i <= n; i++) {
left[i] = cnt1 + left[i - 1];
cnt1 += (arr[i] - '0');
right[n - i + 1] = cnt2 + right[n - i + 2];
cnt2 += (arr[n - i + 1] - '0');
}
for (int i = 1; i <= n; i++) ans[i - 1] = left[i] + right[i];
return ans;
}
}
class Solution {
public:
vector<int> minOperations(string boxes) {
int n = boxes.length();
vector<int> left(n + 5, 0), right(n + 5, 0), ans(n, 0);
int cnt1 = 0, cnt2 = 0;
for (int i = 1; i <= n; i++) {
left[i] = cnt1 + left[i - 1];
cnt1 += (boxes[i - 1] - '0');
right[n - i + 1] = cnt2 + right[n - i + 2];
cnt2 += (boxes[n - i] - '0');
}
for (int i = 1; i <= n; i++) ans[i - 1] = left[i] + right[i];
return ans;
}
};
在计算答案的时候再计算left前缀和的值。首先计算出解法一中right[1]的结果保存在right中,在计算答案的时候更新left和right即可。
class Solution {
public int[] minOperations(String boxes) {
int n = boxes.length();
char[] arr = (" " + boxes).toCharArray();
int left = 0, right = 0, cnt1 = 0, cnt2 = 0;
int[] ans = new int[n];
for (int i = n; i >= 1; i--) {
right += cnt2;
cnt2 += arr[i] - '0';
}
for (int i = 1; i <= n; i++, left += cnt1, right -= cnt2) {
ans[i - 1] = left + right;
cnt1 += arr[i] - '0';
cnt2 -= arr[i] - '0';
}
return ans;
}
}
class Solution {
public:
vector<int> minOperations(string boxes) {
int n = boxes.length();
int left = 0, right = 0, cnt1 = 0, cnt2 = 0;
vector<int> ans(n);
for (int i = n; i >= 1; i--) {
right += cnt2;
cnt2 += boxes[i - 1] - '0';
}
for (int i = 1; i <= n; i++, left += cnt1, right -= cnt2) {
ans[i - 1] = left + right;
cnt1 += boxes[i - 1] - '0';
cnt2 -= boxes[i - 1] - '0';
}
return ans;
}
};
class Solution {
public int[] minOperations(String boxes) {
int n = boxes.length();
char[] arr = (" " + boxes).toCharArray();
int left = 0, cnt1 = 0, cnt2 = 0;
int[] ans = new int[n];
for (int i = n; i >= 1; i--) {
ans[i - 1] += (i < n ? ans[i] : 0) + cnt2;
cnt2 += arr[i] - '0';
}
for (int i = 1; i <= n; i++, left += cnt1) {
ans[i - 1] += left;
cnt1 += arr[i] - '0';
}
return ans;
}
}