问题描述
小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a_i
。其中一些菜中含有蘑菇,s_i
代表第 i 道菜是否含有蘑菇。如果 s_i = '1'
,那么第 i 道菜含有蘑菇,否则没有。
小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1
。
解题思路
这道题目是一个典型的贪心算法问题,目标是尽可能选择低价格的菜品,同时满足约束条件。以下将详细分析题解逻辑并逐步讲解实现代码的思路。
1. 分类菜品
我们首先遍历所有菜品,根据它们是否含有蘑菇,将其划分成两组:
- 不含蘑菇的菜,放入列表
no_mushroom
。 - 含蘑菇的菜,放入列表
mushroom
。
这种分类能够帮助我们在后续处理中更加高效地做出选择。
2. 排序
为了尽可能降低总价格,我们需要优先选择价格最低的菜品。因此,将 mushroom
和 no_mushroom
两个列表按照价格从低到高排序。
3. 贪心选择菜品
在选择菜品时,我们采取以下策略:
- 每次从两个列表中选出价格最低的一道菜。
- 如果当前选中的是含蘑菇的菜,则检查当前已经选了多少道含蘑菇的菜,确保不超过 m 的限制。
- 如果当前选中的是不含蘑菇的菜,则直接选择。
通过这种贪心的方式,可以保证总价格是最低的。
4. 检查是否满足条件
在选择过程中,如果无法满足 k 道菜的要求,例如两个列表的菜品总数量不足 k,或者含蘑菇的菜超过限制 m,则直接返回 -1。
测试样例分析
样例:
输入:
s = "001"
a = [10, 20, 30]
m = 1
k = 2
分析:
- 分为含蘑菇的菜:
mushroom = [30]
,不含蘑菇的菜:no_mushroom = [10, 20]
。 - 优先选择价格最低的两道不含蘑菇的菜:10 和 20。
- 总价格:30。
输出: 30
样例2:
输入:
s = "111"
a = [10, 20, 30]
m = 1
k = 2
分析:
- 全部菜都含有蘑菇:
mushroom = [10, 20, 30]
,no_mushroom = []
。 - m=1 限制只能选一道含蘑菇的菜,但 k=2 要求至少选两道,无法满足条件。
输出: -1
完整代码实现
python
复制代码
def solution(s: str, a: list, m: int, k: int) -> int:
mushroom = []
no_mushroom = []
# 分类菜品
for i in range(len(s)):
if s[i] == "1":
mushroom.append(a[i])
else:
no_mushroom.append(a[i])
# 按价格升序排序
mushroom.sort()
no_mushroom.sort()
# 贪心选择
cost = 0
p, q = 0, 0 # p为不含蘑菇菜指针,q为含蘑菇菜指针
for i in range(k):
if q < len(mushroom) and p < len(no_mushroom) and q < m:
if no_mushroom[p] < mushroom[q]:
cost += no_mushroom[p]
p += 1
else:
cost += mushroom[q]
q += 1
elif p < len(no_mushroom):
cost += no_mushroom[p]
p += 1
elif q < len(mushroom) and q < m:
cost += mushroom[q]
q += 1
else:
return -1 # 无法满足条件
return cost
边界情况分析
-
没有蘑菇菜,且 k>len(no_mushroom):
- 如果可选菜品总数不足,直接返回 -1。
-
所有菜品都含蘑菇,且 k>m:
- m 限制无法满足 k 道菜的需求,返回 -1。
复杂度分析
-
时间复杂度:
- 列表分类:O(n)。
- 排序:O(nlogn)。
- 贪心选择:O(k)。
- 总计:O(nlogn)。
-
空间复杂度:
- 两个额外列表存储分类结果:O(n)。