Medium
题目描述
Alice 和 Bob 是射箭比赛中的对手。比赛规则如下:
- Alice 先射
numArrows支箭,然后 Bob 射numArrows支箭。 - 得分计算方式如下:
- 靶子有从 0 到 11 的整数得分区域。
- 对于得分为 k(0 到 11 之间)的每个区域,假设 Alice 和 Bob 分别在该区域射了 ak 和 bk 支箭。如果 ak >= bk,那么 Alice 得到 k 分。如果 ak < bk,那么 Bob 得到 k 分。
- 但是,如果 ak == bk == 0,那么没有人得到 k 分。
例如,如果 Alice 和 Bob 都在得分为 11 的区域射了 2 支箭,那么 Alice 得到 11 分。另一方面,如果 Alice 在得分为 11 的区域射了 0 支箭,而 Bob 在同一区域射了 2 支箭,那么 Bob 得到 11 分。
给定整数 numArrows 和大小为 12 的整数数组 aliceArrows,其中 aliceArrows[i] 表示 Alice 在得分为 i 的区域射的箭数。现在,Bob 想要最大化他能获得的总分数。
返回数组 bobArrows,表示 Bob 在得分为 0 到 11 的每个区域射的箭数。bobArrows 中值的总和应该等于 numArrows。
如果有多种方式使 Bob 获得最大总分数,返回其中任何一种。
示例 1:
输入:numArrows = 9, aliceArrows = [1,1,0,1,0,0,2,1,0,1,2,0]
输出:[0,0,0,0,1,1,0,0,1,2,3,1]
解释:Bob 总共得到 4 + 5 + 8 + 9 + 10 + 11 = 47 分。
可以证明 Bob 无法获得超过 47 分的分数。
示例 2:
输入:numArrows = 3, aliceArrows = [0,0,1,0,0,0,0,0,0,0,0,2]
输出:[0,0,0,0,0,0,0,0,1,1,1,0]
解释:Bob 总共得到 8 + 9 + 10 = 27 分。
可以证明 Bob 无法获得超过 27 分的分数。
约束条件:
- 1 <= numArrows <= 10^5
- aliceArrows.length == bobArrows.length == 12
- 0 <= aliceArrows[i], bobArrows[i] <= numArrows
- sum(aliceArrows[i]) == numArrows
解题思路
这是一个典型的枚举问题。由于只有12个得分区域,我们可以使用位运算枚举所有可能的获胜组合。
核心思路:
- 对于每个得分区域 i,Bob要想获得该区域的分数,他必须射比Alice更多的箭,即至少射
aliceArrows[i] + 1支箭 - 由于总共只有12个区域,我们可以使用12位的二进制数来表示Bob选择获胜的区域组合
- 对于每个组合,计算需要的总箭数和能获得的总分数
- 如果箭数不超过限制,更新最优解
算法步骤:
- 枚举所有可能的获胜组合(0到2^12-1)
- 对于每个组合,计算Bob需要的箭数和能获得的分数
- 如果箭数合法且分数更高,更新最优解
- 将剩余的箭全部分配给得分为0的区域
时间复杂度为O(2^12) = O(4096),完全可以接受。
代码实现
class Solution {
public:
vector<int> maximumBobPoints(int numArrows, vector<int>& aliceArrows) {
int maxScore = 0;
int bestMask = 0;
// 枚举所有可能的获胜组合
for (int mask = 0; mask < (1 << 12); mask++) {
int arrowsNeeded = 0;
int score = 0;
for (int i = 0; i < 12; i++) {
if (mask & (1 << i)) {
arrowsNeeded += aliceArrows[i] + 1;
score += i;
}
}
if (arrowsNeeded <= numArrows && score > maxScore) {
maxScore = score;
bestMask = mask;
}
}
vector<int> bobArrows(12, 0);
int remainingArrows = numArrows;
for (int i = 0; i < 12; i++) {
if (bestMask & (1 << i)) {
bobArrows[i] = aliceArrows[i] + 1;
remainingArrows -= bobArrows[i];
}
}
// 将剩余的箭分配给得分为0的区域
bobArrows[0] += remainingArrows;
return bobArrows;
}
};
class Solution:
def maximumBobPoints(self, numArrows: int, aliceArrows: List[int]) -> List[int]:
max_score = 0
best_mask = 0
# 枚举所有可能的获胜组合
for mask in range(1 << 12):
arrows_needed = 0
score = 0
for i in range(12):
if mask & (1 << i):
arrows_needed += aliceArrows[i] + 1
score += i
if arrows_needed <= numArrows and score > max_score:
max_score = score
best_mask = mask
bob_arrows = [0] * 12
remaining_arrows = numArrows
for i in range(12):
if best_mask & (1 << i):
bob_arrows[i] = aliceArrows[i] + 1
remaining_arrows -= bob_arrows[i]
# 将剩余的箭分配给得分为0的区域
bob_arrows[0] += remaining_arrows
return bob_arrows
public class Solution {
public int[] MaximumBobPoints(int numArrows, int[] aliceArrows) {
int maxScore = 0;
int bestMask = 0;
// 枚举所有可能的获胜组合
for (int mask = 0; mask < (1 << 12); mask++) {
int arrowsNeeded = 0;
int score = 0;
for (int i = 0; i < 12; i++) {
if ((mask & (1 << i)) != 0) {
arrowsNeeded += aliceArrows[i] + 1;
score += i;
}
}
if (arrowsNeeded <= numArrows && score > maxScore) {
maxScore = score;
bestMask = mask;
}
}
int[] bobArrows = new int[12];
int remainingArrows = numArrows;
for (int i = 0; i < 12; i++) {
if ((bestMask & (1 << i)) != 0) {
bobArrows[i] = aliceArrows[i] + 1;
remainingArrows -= bobArrows[i];
}
}
// 将剩余的箭分配给得分为0的区域
bobArrows[0] += remainingArrows;
return bobArrows;
}
}
var maximumBobPoints = function(numArrows, aliceArrows) {
let maxScore = 0;
let bestMask = 0;
// 枚举所有可能的获胜组合
for (let mask = 0; mask < (1 << 12); mask++) {
let arrowsNeeded = 0;
let score = 0;
for (let i = 0; i < 12; i++) {
if (mask & (1 << i)) {
arrowsNeeded += aliceArrows[i] + 1;
score += i;
}
}
if (arrowsNeeded <= numArrows && score > maxScore) {
maxScore = score;
bestMask = mask;
}
}
let bobArrows = new Array(12).fill(0);
let remainingArrows = numArrows;
for (let i = 0; i < 12; i++) {
if (bestMask & (1 << i)) {
bobArrows[i] = aliceArrows[i] + 1;
remainingArrows -= bobArrows[i];
}
}
// 将剩余的箭分配给得分为0的区域
bobArrows[0] += remainingArrows;
return bobArrows;
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(2^12) = O(4096),需要枚举所有可能的获胜组合 |
| 空间复杂度 | O(1),只使用了常数额外空间 |