饭馆菜品选择问题| 豆包MarsCode AI刷题

44 阅读3分钟

问题描述

小C来到了一家饭馆,这里共有 nn 道菜,第 ii 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 ii 道菜是否含有蘑菇。如果 s_i = '1',那么第 ii 道菜含有蘑菇,否则没有。

小C希望点 kk 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 mm 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1

分析问题

  1. 输入:

    • s: 一个字符串,表示每道菜是否含有蘑菇。
    • a: 一个整数数组,表示每道菜的价格。
    • m: 整数,表示最多可以选含有蘑菇的菜的数量。
    • k: 整数,表示总共需要选的菜的数量。
  2. 简化:

    • 容器a中每个数的位置标号对应s中的位置,最多只能携带m个标号为1的数,返回最少k个数的和
    • 可以使用一个 pair 数组来存储每道菜的价格和是否含有蘑菇的信息。

算法步骤

  1. 初始化:

    • 创建一个 pair 数组,存储每道菜的价格和是否含有蘑菇的信息。
    • pair 数组按价格从小到大排序。
  2. 选择菜品:

    • 遍历排序后的 pair 数组,优先选择价格较低的菜。
    • 使用两个计数器:一个记录已经选择的含有蘑菇的菜的数量,另一个记录已经选择的菜的总数量。
    • 如果当前菜含有蘑菇且含有蘑菇的菜的数量未达到上限 m,则选择该菜。
    • 如果当前菜不含蘑菇,则直接选择该菜。
    • 如果已经选择了 k 道菜,则停止选择。
  3. 检查结果:

    • 如果已经选择了 k 道菜,则返回总价格。
    • 如果无法选择 k 道菜,则返回 -1

代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

long long solution(const std::string &s, std::vector<int> &a, int m, int k) {
    int n = a.size();
    // 创建一个pair数组,包含数值和对应的s中的标记
    std::vector<std::pair<int, char>> pairs;
    for (int i = 0; i < n; i++) {
        pairs.push_back({a[i], s[i]});
    }

    // 按照数值大小对pairs进行排序,数值小的在前
    std::sort(pairs.begin(), pairs.end());

    int onesSelected = 0;
    long long sum = 0;
    // 遍历排序后的pairs,选择最小的k个数
    for (const auto &pair : pairs) {
        if (k == 0) {
            break;
        }
        if (pair.second == '0') {
            sum += pair.first;
            k--;
        } else if (onesSelected < m) {
            sum += pair.first;
            k--;
            onesSelected++;
        }
    }

    // 如果k不为0,说明我们没有足够的'0'来满足k的需求,返回-1
    if (k != 0) {
        return -1;
    }

    return sum;
}

分析时间复杂度

  1. 创建pair数组

    • 这一步涉及到遍历字符串s和数组a的长度n,将每个元素和对应的字符放入pairs数组中。这一步的时间复杂度是O(n)
  2. 排序pairs数组

    • 使用std::sortpairs数组进行排序,排序算法通常是快速排序、堆排序或归并排序,平均时间复杂度为O(n log n)
  3. 遍历pairs数组

    • 这一步涉及到遍历排序后的pairs数组,最坏情况下需要遍历整个数组,即O(n)。但在最佳情况下,可能只需要遍历k个元素,即O(k)

综合以上步骤,整个算法的时间复杂度主要由排序步骤决定,因此整体时间复杂度为O(n log n),其中n是数组a的长度。