《最大化未出现自然数问题》和《最大化糖果美味值问题》| 豆包MarsCode AI刷题

147 阅读4分钟

今天我们将在豆包MarsCode AI刷题平台上,完成《最大化未出现自然数问题》与《最大化糖果美味值问题》这两个算法问题,通过这些练习提升用户解决此类问题的能力

《最大化未出现自然数问题》题面如下:

图片.png

问题理解

很容易发现,如果当前已知最大的可以得到的自然数为N,那么为了得到N+1,只需要存在一个未被使用的数X,满足X<=N+1

实现思路

  1. 排序集合:首先,对输入的集合 a 进行排序。排序的目的是为了能够快速检查集合中是否存在未被使用且小于给定数字的数。
  2. 检查自然数是否出现:对于每个自然数 maxNum,检查集合中是否有小于 maxNum 的数。如果有,则移动指针 apos
  3. 判断最大未出现自然数:如果 apos 小于 maxNum,说明 maxNum 无法得到,即最大的未出现自然数。
  4. 返回结果:如果没有找到未出现的自然数,则返回 n+1

具体实现

#include <bits/stdc++.h>

using namespace std;

int solution(int n, vector<int> a) {
    // 对集合进行排序
    sort(a.begin(), a.end());
    
    int apos = 0; // 初始化指针,用于遍历集合
    
    // maxNum是当前最大的未出现自然数
    for (int maxNum = 0;; maxNum++) {
        // 移动指针,直到找到大于等于maxNum的数
        while (apos < n && a[apos] < maxNum) {
            apos++;
        }
        
        // 如果指针apos小于maxNum,说明maxNum无法达到,即最大的未出现自然数
        if (apos < maxNum) {
            return maxNum - 1; // 返回最大的未出现自然数
        }
    }
    
    // 如果没有找到未出现的自然数,返回n+1
    return n + 1;
}

int main() {
    // 测试用例
    cout << (solution(5, {5, 0, 0, 2, 2}) == 4) << endl;
    cout << (solution(6, {1, 0, 3, 4, 4, 5}) == 2) << endl;
    cout << (solution(4, {0, 1, 2, 3}) == 4) << endl;
    cout << (solution(7, {7, 6, 5, 4, 3, 2, 1}) == 0) << endl;
    cout << (solution(5, {0, 1, 2, 1, 3}) == 5) << endl;
    
    return 0;
}

《最大化糖果美味值问题》题面如下:

图片.png

解题思路

这个问题可以通过动态规划来解决。我们需要找到一种方法来选择糖果,使得美味值之和最大,同时遵守题目中给出的限制规则。

数据结构的选择

我们使用一个二维数组 f 来存储动态规划的状态。f[i][0] 表示不选择第 i 个糖果时的最大美味值,f[i][1] 表示选择第 i 个糖果时的最大美味值。同时为了快速进行状态转移,我们用premax2这个变量记录max{f[0],...,f[i-3]},用premax0记录max{f[0],...,f[i-1]}

算法步骤

  1. 初始化:创建一个二维数组 f,初始值为 0

  2. 状态转移

    • 如果当前糖果不选,那么最大美味值就是之前所有可能的选择中的最大值。
    • 如果当前糖果选,那么最大美味值就是剔除前两个糖果的所有可能的选择的最大值加上当前糖果的美味值。
  3. 更新最大值:在每次迭代中,更新局部最大美味值premax2premax0,以及全局最大美味值ret

具体实现

#include <bits/stdc++.h>

using namespace std;

int solution(int n, std::vector<int> a) {
    // 初始化返回值和动态规划数组
    int ret = 0;
    std::vector<std::vector<int>> f(n + 1, std::vector<int>(2, 0));
    int premax2 = 0, premax0 = 0;

    for (int i = 0; i < n; i++) {
        // 不选择当前糖果的情况
        f[i + 1][0] = premax0;
        // 选择当前糖果的情况
        f[i + 1][1] = premax2 + a[i];

        // 更新premax2,即剔除前两个糖果的最大美味值
        if (i - 2 >= 0 && premax2 < max(f[i - 2 + 1][0], f[i - 2 + 1][1])) {
            premax2 = max(f[i - 2 + 1][0], f[i - 2 + 1][1]);
        }

        // 更新premax0,即所有可能得选择中的最大美味值
        if (premax0 < max(f[i + 1][0], f[i + 1][1])) {
            premax0 = max(f[i + 1][0], f[i + 1][1]);
        }

        // 更新全局最大美味值
        ret = max({ret, f[i + 1][0], f[i + 1][1]});
    }

    return ret;
}

int main() {
    std::cout << (solution(7, std::vector<int>{3, 1, 2, 7, 10, 2, 4}) == 14) << std::endl;
    std::cout << (solution(5, std::vector<int>{1, 10, 2, 5, 8}) == 18) << std::endl;
    std::cout << (solution(6, std::vector<int>{4, 5, 6, 1, 2, 3}) == 9) << std::endl;
    std::cout << (solution(13, std::vector<int>{2, 11, 7, 8, 6, 12, 16, 2, 2, 11, 13, 10, 7}) == 45) << std::endl;
    return 0;
}

借助豆包MarsCode AI刷题平台,我们不仅高效地解决了《最大化未出现自然数问题》和《最大化糖果美味值问题》,还加深了对相关算法和数据结构的理解,后续会借助豆包MarsCode AI给大家展示更多题目的解法。