题目解析:
题目:选择豆包MarsCode AI 刷题(代码练习)题库中的任意题目进行解析,如思路、图解、代码详解。
题目描述
小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 i 道菜是否含有蘑菇。如果 s_i = '1',那么第 i 道菜含有蘑菇,否则没有。
小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1。
思路解析
-
问题理解:
- 我们需要从
n道菜中选择k道菜,使得总价格最小。 - 选择的菜中最多只能有
m道菜含有蘑菇。 - 如果无法满足条件,返回
-1。
- 我们需要从
-
数据结构选择:
- 使用两个列表分别存储不含蘑菇的菜和含有蘑菇的菜。
- 对这两个列表分别进行排序,以便于选择价格最低的菜。
-
算法步骤:
- 遍历
s和a,将不含蘑菇的菜和含有蘑菇的菜分别存储在两个列表中。 - 对这两个列表按价格进行排序。
- 使用双指针或贪心算法,从两个列表中选择菜,确保总价格最小且满足蘑菇菜的数量限制。
- 如果无法满足条件,返回
-1。
- 遍历
图解
假设我们有以下输入:
s = "001"a = [10, 20, 30]m = 1k = 2
-
将菜分为不含蘑菇和含有蘑菇的两组:
- 不含蘑菇的菜:
[10, 20] - 含有蘑菇的菜:
[30]
- 不含蘑菇的菜:
-
对两组菜按价格排序:
- 不含蘑菇的菜:
[10, 20] - 含有蘑菇的菜:
[30]
- 不含蘑菇的菜:
-
选择菜:
- 选择不含蘑菇的菜
10和20,总价格为30。
- 选择不含蘑菇的菜
代码详解
public class Main { public static long solution(String s, int[] a, int m, int k) { // 将菜分为不含蘑菇和含有蘑菇的两组 List noMushroom = new ArrayList<>(); List mushroom = new ArrayList<>();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '0') {
noMushroom.add(a[i]);
} else {
mushroom.add(a[i]);
}
}
// 对两组菜按价格排序
Collections.sort(noMushroom);
Collections.sort(mushroom);
// 使用双指针或贪心算法选择菜
int noMushroomIndex = 0;
int mushroomIndex = 0;
long totalPrice = 0;
int selectedCount = 0;
int mushroomCount = 0;
while (selectedCount < k) {
if (noMushroomIndex < noMushroom.size() && (mushroomIndex >= mushroom.size() || noMushroom.get(noMushroomIndex) <= mushroom.get(mushroomIndex))) {
totalPrice += noMushroom.get(noMushroomIndex);
noMushroomIndex++;
} else if (mushroomIndex < mushroom.size()) {
if (mushroomCount < m) {
totalPrice += mushroom.get(mushroomIndex);
mushroomIndex++;
mushroomCount++;
} else {
break;
}
} else {
break;
}
selectedCount++;
}
// 如果无法满足条件,返回 -1
if (selectedCount < k) {
return -1;
}
return totalPrice;
}
public static void main(String[] args) {
System.out.println(solution("001", new int[]{10, 20, 30}, 1, 2) == 30);
System.out.println(solution("111", new int[]{10, 20, 30}, 1, 2) == -1);
System.out.println(solution("0101", new int[]{5, 15, 10, 20}, 2, 3) == 30);
}
}
知识总结
在解决这个问题的过程中,我们学习了以下知识点:
- 贪心算:在每一步选择当前最优解,以期望最终得到全局最优解。
- 双指针技术:用于在两个有序列表中选择元素。
- 列表排序:对列表进行排序以便于选择最小价格的菜。
学习建议
- 理解题目:在开始编写代码之前,确保完全理解题目的要求和限制。
- 数据结构选择:根据题目的特点选择合适的数据结构,如列表、数组等。
- 算法设计:设计合适的算法,如贪心算法、动态规划等,以解决问题。
- 代码实现*:在实现代码时,注意边界条件和异常处理。
学习计划
- 制定刷题计划:每天刷一定数量的题目,逐步提高难度。
- 错题分析对于做错的题目,分析错误原因,并记录下来以便后续复习。
- 总结归:定期总结刷题过程中遇到的知识点和技巧,形成自己的知识库。
工具运用
- 结合AI刷题:利用AI刷题功能,获取解题思路和代码提示。
- 结合其他资源:结合书籍、在线课程等资源,全面提升编程能力。
- 实践应用:将学到的知识应用到实际项目中,加深理解。
通过以上方法,可以有效提高编程能力和解题技巧