1.题目
问题描述
小U在公司年会上运气极佳,赢得了一等奖。作为一等奖得主,他有机会在一排红包中做两次切割,将红包分成三部分,要求第一部分和第三部分的红包总金额相等。他可以获得的金额是第一部分红包的总金额。帮小U计算出他能从这些红包中拿到的最大奖金金额。
测试样例
样例1:
输入:redpacks = [1, 3, 4, 6, 7, 14]
输出:
14
样例2:
输入:redpacks = [10000]
输出:
0
样例3:
输入:redpacks = [10, 10, 10, 10]
输出:
20
样例4:
输入:redpacks = [5, 5, 10, 20, 10, 5, 5]
输出:
20
样例5:
输入:redpacks = [7, 7, 7, 21, 7, 7]
输出:
14
2.思路
- 计算前缀和数组:首先计算红包数组的前缀和数组
prefixSum。 - 遍历可能的切割点:我们需要遍历所有可能的切割点
i和j,其中i是第一次切割的位置,j是第二次切割的位置。 - 检查条件:对于每一对
(i, j),检查prefixSum[i]是否等于prefixSum[n-1] - prefixSum[j],其中n是红包数组的长度。 - 更新最大值:如果条件满足,更新最大奖金金额。
3.代码
#include <iostream>
#include <vector>
using namespace std;
int solution(std::vector<int> redpacks) {
// Please write your code here
int n = redpacks.size();
vector<int> prefixSum(n + 1, 0); //前缀和数组
for (int i = 1; i < n + 1; i++) {
prefixSum[i] = prefixSum[i -1] + redpacks[i - 1];
}
int max_bonus = 0;
// 遍历所有的切割点
for (int i = 0; i < n - 1; i++) {
for (int j = i; j < n - 1; j++) {
//在第i个红包和第j个红包后划分
if (prefixSum[i + 1] == prefixSum[n + 1] - prefixSum[j + 1]){
max_bonus = max(max_bonus, prefixSum[i + 1]);
}
}
}
return max_bonus;
}
int main() {
// You can add more test cases here
std::vector<int> redpacks1 = {1, 3, 4, 6, 7, 14};
std::vector<int> redpacks2 = {10000};
std::vector<int> redpacks3 = {52, 13, 61, 64, 42, 26, 4, 27, 25};
std::vector<int> redpacks4 = {2, 5, 50, 30, 60, 52, 26, 5, 74, 83, 34, 96, 6, 88, 94, 80, 64, 22, 97, 47, 46, 25, 24, 43, 76, 24, 2, 42, 51, 96, 97, 87, 47, 93, 11, 98, 41, 54, 18, 16, 11, 96, 34, 36, 87, 24, 32, 27, 62, 72, 54, 14, 67, 5, 21, 20, 44, 55, 3, 82, 19, 45, 1, 52, 14, 44, 46, 39, 83, 27, 30, 87, 61, 56, 59, 10, 83, 80, 42, 44, 75, 39, 43, 41, 23, 93, 73, 50, 94, 94, 82, 46, 87, 60, 94, 47, 52, 67, 22, 50, 49, 8, 9, 30, 62, 87, 13, 11};
std::cout << (solution(redpacks1) == 14) << std::endl;
std::cout << (solution(redpacks2) == 0) << std::endl;
std::cout << (solution(redpacks3) == 52) << std::endl;
std::cout << (solution(redpacks4) == 2627) << std::endl;
return 0;
}
代码问题:
- 前缀和数组越界问题:
- 在计算前缀和时,
prefixSum[n + 1]会导致数组越界,因为prefixSum的大小是n + 1,而n + 1超出了数组的范围。
- 在计算前缀和时,
- 前缀和数组初始化问题:
prefixSum[n + 1]应该是prefixSum[n],因为prefixSum的大小是n + 1,而prefixSum[n]是最后一个元素。
- 条件判断错误:
if (prefixSum[i + 1] == prefixSum[n + 1] - prefixSum[j + 1])中的prefixSum[n + 1]应该是prefixSum[n],因为prefixSum[n]是整个数组的总和。
- 逻辑错误:
- 在遍历切割点时,
j应该从i + 1开始,而不是从i开始,因为i和j必须是不同的切割点。
- 在遍历切割点时,
修改:
- 修正前缀和数组越界问题:
- 将
prefixSum[n + 1]改为prefixSum[n]。
- 将
- 修正条件判断错误:
- 将
prefixSum[n + 1]改为prefixSum[n]。
- 将
- 修正逻辑错误:
- 将
j的起始值改为i + 1。
- 将
#include <iostream>
#include <vector>
using namespace std;
int solution(std::vector<int> redpacks) {
// Please write your code here
int n = redpacks.size();
vector<int> prefixSum(n + 1, 0); //前缀和数组
for (int i = 1; i < n + 1; i++) {
prefixSum[i] = prefixSum[i -1] + redpacks[i - 1];
}
int max_bonus = 0;
// 遍历所有的切割点
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n - 1; j++) {
//在第i个红包和第j个红包后划分
if (prefixSum[i + 1] == prefixSum[n] - prefixSum[j + 1]){
max_bonus = max(max_bonus, prefixSum[i + 1]);
}
}
}
return max_bonus;
}
int main() {
// You can add more test cases here
std::vector<int> redpacks1 = {1, 3, 4, 6, 7, 14};
std::vector<int> redpacks2 = {10000};
std::vector<int> redpacks3 = {52, 13, 61, 64, 42, 26, 4, 27, 25};
std::vector<int> redpacks4 = {2, 5, 50, 30, 60, 52, 26, 5, 74, 83, 34, 96, 6, 88, 94, 80, 64, 22, 97, 47, 46, 25, 24, 43, 76, 24, 2, 42, 51, 96, 97, 87, 47, 93, 11, 98, 41, 54, 18, 16, 11, 96, 34, 36, 87, 24, 32, 27, 62, 72, 54, 14, 67, 5, 21, 20, 44, 55, 3, 82, 19, 45, 1, 52, 14, 44, 46, 39, 83, 27, 30, 87, 61, 56, 59, 10, 83, 80, 42, 44, 75, 39, 43, 41, 23, 93, 73, 50, 94, 94, 82, 46, 87, 60, 94, 47, 52, 67, 22, 50, 49, 8, 9, 30, 62, 87, 13, 11};
std::cout << (solution(redpacks1) == 14) << std::endl;
std::cout << (solution(redpacks2) == 0) << std::endl;
std::cout << (solution(redpacks3) == 52) << std::endl;
std::cout << (solution(redpacks4) == 2627) << std::endl;
return 0;
}
样例3:
输入:redpacks = [10, 10, 10, 10]
输出:
20
样例三过不了,不太理解为什么输出是20。
再次修改代码,将j的初始值改为i,也就是说两个分割点可以相同,成功通过所有样例。
正确代码
#include <iostream>
#include <vector>
using namespace std;
int solution(std::vector<int> redpacks) {
// Please write your code here
int n = redpacks.size();
vector<int> prefixSum(n + 1, 0); //前缀和数组
for (int i = 1; i < n + 1; i++) {
prefixSum[i] = prefixSum[i -1] + redpacks[i - 1];
}
int max_bonus = 0;
// 遍历所有的切割点
for (int i = 0; i < n - 1; i++) {
for (int j = i; j < n - 1; j++) {
//在第i个红包和第j个红包后划分
if (prefixSum[i + 1] == prefixSum[n] - prefixSum[j + 1]){
max_bonus = max(max_bonus, prefixSum[i + 1]);
}
}
}
return max_bonus;
}
int main() {
// You can add more test cases here
std::vector<int> redpacks1 = {1, 3, 4, 6, 7, 14};
std::vector<int> redpacks2 = {10000};
std::vector<int> redpacks3 = {52, 13, 61, 64, 42, 26, 4, 27, 25};
std::vector<int> redpacks4 = {2, 5, 50, 30, 60, 52, 26, 5, 74, 83, 34, 96, 6, 88, 94, 80, 64, 22, 97, 47, 46, 25, 24, 43, 76, 24, 2, 42, 51, 96, 97, 87, 47, 93, 11, 98, 41, 54, 18, 16, 11, 96, 34, 36, 87, 24, 32, 27, 62, 72, 54, 14, 67, 5, 21, 20, 44, 55, 3, 82, 19, 45, 1, 52, 14, 44, 46, 39, 83, 27, 30, 87, 61, 56, 59, 10, 83, 80, 42, 44, 75, 39, 43, 41, 23, 93, 73, 50, 94, 94, 82, 46, 87, 60, 94, 47, 52, 67, 22, 50, 49, 8, 9, 30, 62, 87, 13, 11};
std::cout << (solution(redpacks1) == 14) << std::endl;
std::cout << (solution(redpacks2) == 0) << std::endl;
std::cout << (solution(redpacks3) == 52) << std::endl;
std::cout << (solution(redpacks4) == 2627) << std::endl;
return 0;
}
4.参考资料
57. 最大相等分割红包金额 | 豆包MarsCode AI刷题本题要求通过两次切割红包,确保第一部分和第三部分金额相 - 掘金