57.最大相等分割红包余额|Marscode AI刷题

88 阅读6分钟

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.思路

  1. 计算前缀和数组:首先计算红包数组的前缀和数组 prefixSum
  2. 遍历可能的切割点:我们需要遍历所有可能的切割点 i 和 j,其中 i 是第一次切割的位置,j 是第二次切割的位置。
  3. 检查条件:对于每一对 (i, j),检查 prefixSum[i] 是否等于 prefixSum[n-1] - prefixSum[j],其中 n 是红包数组的长度。
  4. 更新最大值:如果条件满足,更新最大奖金金额。

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;
}

代码问题:

  1. 前缀和数组越界问题
    • 在计算前缀和时,prefixSum[n + 1] 会导致数组越界,因为 prefixSum 的大小是 n + 1,而 n + 1 超出了数组的范围。
  2. 前缀和数组初始化问题
    • prefixSum[n + 1] 应该是 prefixSum[n],因为 prefixSum 的大小是 n + 1,而 prefixSum[n] 是最后一个元素。
  3. 条件判断错误
    • if (prefixSum[i + 1] == prefixSum[n + 1] - prefixSum[j + 1]) 中的 prefixSum[n + 1] 应该是 prefixSum[n],因为 prefixSum[n] 是整个数组的总和。
  4. 逻辑错误
    • 在遍历切割点时,j 应该从 i + 1 开始,而不是从 i 开始,因为 i 和 j 必须是不同的切割点。

修改:

  1. 修正前缀和数组越界问题
    • 将 prefixSum[n + 1] 改为 prefixSum[n]
  2. 修正条件判断错误
    • 将 prefixSum[n + 1] 改为 prefixSum[n]
  3. 修正逻辑错误
    • 将 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。

image.png

再次修改代码,将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刷题本题要求通过两次切割红包,确保第一部分和第三部分金额相 - 掘金