学习体验与故事

83 阅读4分钟

题目解析:

题目:选择豆包MarsCode AI 刷题(代码练习)题库中的任意题目进行解析,如思路、图解、代码详解。

题目描述

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

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

思路解析

  1. 问题理解:

    • 我们需要从 n 道菜中选择 k 道菜,使得总价格最小。
    • 选择的菜中最多只能有 m 道菜含有蘑菇。
    • 如果无法满足条件,返回 -1
  2. 数据结构选择:

    • 使用两个列表分别存储不含蘑菇的菜和含有蘑菇的菜。
    • 对这两个列表分别进行排序,以便于选择价格最低的菜。
  3. 算法步骤:

    • 遍历 s 和 a,将不含蘑菇的菜和含有蘑菇的菜分别存储在两个列表中。
    • 对这两个列表按价格进行排序。
    • 使用双指针或贪心算法,从两个列表中选择菜,确保总价格最小且满足蘑菇菜的数量限制。
    • 如果无法满足条件,返回 -1

图解

假设我们有以下输入:

  • s = "001"
  • a = [10, 20, 30]
  • m = 1
  • k = 2
  1. 将菜分为不含蘑菇和含有蘑菇的两组:

    • 不含蘑菇的菜:[10, 20]
    • 含有蘑菇的菜:[30]
  2. 对两组菜按价格排序:

    • 不含蘑菇的菜:[10, 20]
    • 含有蘑菇的菜:[30]
  3. 选择菜:

    • 选择不含蘑菇的菜 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);
}
}

知识总结

在解决这个问题的过程中,我们学习了以下知识点:

  • 贪心算:在每一步选择当前最优解,以期望最终得到全局最优解。
  • 双指针技术:用于在两个有序列表中选择元素。
  • 列表排序:对列表进行排序以便于选择最小价格的菜。

学习建议

  1. 理解题目:在开始编写代码之前,确保完全理解题目的要求和限制。
  2. 数据结构选择:根据题目的特点选择合适的数据结构,如列表、数组等。
  3. 算法设计:设计合适的算法,如贪心算法、动态规划等,以解决问题。
  4. 代码实现*:在实现代码时,注意边界条件和异常处理。

学习计划

  1. 制定刷题计划:每天刷一定数量的题目,逐步提高难度。
  2. 错题分析对于做错的题目,分析错误原因,并记录下来以便后续复习。
  3. 总结归:定期总结刷题过程中遇到的知识点和技巧,形成自己的知识库。

工具运用

  1. 结合AI刷题:利用AI刷题功能,获取解题思路和代码提示。
  2. 结合其他资源:结合书籍、在线课程等资源,全面提升编程能力。
  3. 实践应用:将学到的知识应用到实际项目中,加深理解。

通过以上方法,可以有效提高编程能力和解题技巧