青训营X豆包MarsCode技术训练营第二课 | 豆包MarsCode AI 刷题

49 阅读5分钟

题目

饭馆菜品选择问题

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

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

一、题目思路分析

  1. 需求理解
  • 题目给定了一系列菜品,每道菜有价格(用数组 a 表示)和是否含蘑菇的属性(用字符串 s 表示)。要求在点菜时满足点 k 道菜,且所点菜品中最多只有 m 道菜含有蘑菇的条件下,使得总价格尽可能低。如果无法按要求选菜,则输出 -1。
  1. 解决思路及对应代码片段: - 菜品分类
  • 首先需要将菜品按照是否含蘑菇进行分类,分别统计不含蘑菇的菜品价格数组和含蘑菇的菜品价格数组,并记录各自的数量。 - 代码实现如下: java int n = s.length(); int[] noMushroom = new int[n]; int[] mushroom = new int[n]; int noMushroomCount = 0, mushroomCount = 0; for (int i = 0; i < n; i++) { if (s.charAt(i) == '0') { noMushroom[noMushroomCount++] = a[i]; } else { mushroom[mushroomCount++] = a[i]; } } -
  • 排序操作
    • 然后对这两类菜品的价格数组分别进行排序,以便后续能方便地选取价格较低的菜品。 - 代码中使用 Arrays.sort 方法实现排序: java Arrays.sort(noMushroom, 0, noMushroomCount); Arrays.sort(mushroom, 0, mushroomCount);
    • 利用优先队列计算最小总价格: - 接下来通过循环尝试不同数量的含蘑菇菜品(从0到 m 与含蘑菇菜品实际数量的最小值),在每次尝试中,根据已确定的含蘑菇菜品数量,计算出还需要选择的不含蘑菇菜品数量,然后将相应的菜品价格相加得到一种点菜组合的总价格。 - 首先创建一个优先队列来存储不同组合的总价格: java PriorityQueue<Long> pq = new PriorityQueue<>(); - 然后通过循环进行不同组合的尝试: java for (int i = 0; i <= Math.min(m, mushroomCount); i++) { if (k - i <= noMushroomCount) { long sum = 0; for (int j = 0; j < i; j++) { sum += mushroom[j]; } for (int j = 0; j < k - i; j++) { sum += noMushroom[j]; } pq.offer(sum); } } - 在上述循环中,对于每个可能的含蘑菇菜品数量 i,先判断如果按照当前含蘑菇菜品数量 i,剩余需要选择的不含蘑菇菜品数量(k - i)是否在不含蘑菇菜品数量的范围内(k - i <= noMushroomCount)。如果满足条件,就计算这种点菜组合的总价格 sum,先累加 i 个含蘑菇菜品的价格(通过遍历含蘑菇菜品价格数组的前 i 个元素),再累加 k - i 个不含蘑菇菜品的价格(通过遍历不含蘑菇菜品价格数组的前 k - i 个元素),最后将 sum 放入优先队列 pq 中。
    • 返回结果: - 将所有满足条件的点菜组合总价格放入优先队列(小顶堆)中,这样优先队列的队首元素就是最小的总价格。最后根据优先队列是否为空来判断是否能满足点菜要求,如果不为空则返回队首元素作为最小总价格,否则返回 -1。 - 代码实现如下: java return pq.isEmpty()? -1 : pq.poll();
  • 二、代码结构分析 1.

  • 变量定义与初始化: - 在 solution 方法中,首先获取菜品的总数 n,然后定义了两个数组 noMushroommushroom 分别用于存储不含蘑菇和含蘑菇的菜品价格,同时定义了 noMushroomCountmushroomCount 来记录这两类菜品的数量,初始值都为0。
    1. 菜品分类: - 通过遍历表示菜品是否含蘑菇的字符串 s 和价格数组 a,根据 s.charAt(i) 的值将菜品价格分别放入对应的 noMushroommushroom 数组中,并相应地更新 noMushroomCountmushroomCount
    1. 排序操作: - 使用 Arrays.sort 方法对 noMushroom 数组和 mushroom 数组分别进行排序,排序范围是从索引0到各自的数量(noMushroomCountmushroomCount),这样能保证数组内的价格是从小到大排列的,方便后续选取价格较低的菜品。
    1. 利用优先队列计算最小总价格: - 创建了一个 PriorityQueue<Long> 类型的优先队列 pq,它会自动按照元素的大小(这里是总价格)进行排序,默认是小顶堆,即队首元素是最小的。 - 通过一个循环,尝试不同数量的含蘑菇菜品(i 从0到 Math.min(m, mushroomCount))。在每次循环中,先判断如果按照当前含蘑菇菜品数量 i,剩余需要选择的不含蘑菇菜品数量(k - i)是否在不含蘑菇菜品数量的范围内(k - i <= noMushroomCount)。如果满足条件,就计算这种点菜组合的总价格 sum,先累加 i 个含蘑菇菜品的价格(通过遍历含蘑菇菜品价格数组的前 i 个元素),再累加 k - i 个不含蘑菇菜品的价格(通过遍历不含蘑菇菜品价格数组的前 k - i 个元素),最后将 sum 放入优先队列 pq 中。
    1. 返回结果: - 根据优先队列 pq 是否为空来判断是否能满足点菜要求。如果 pq 为空,说明没有找到满足条件的点菜组合,返回 -1;否则,返回 pq.poll(),即取出队首元素,也就是满足条件的最小总价格。