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

130 阅读5分钟

解析与图解

问题描述

在一个超市中,有一个包含 n 个格子的货物架,每个格子中放有一种商品,商品用小写字母 az 表示。顾客进入超市后,会依次从第一个格子查找到第 n 个格子,寻找他们想要购买的商品。如果在某个格子中找到该商品,顾客就会购买它并离开;如果中途遇到一个空格子,或者查找完所有格子还没有找到想要的商品,顾客也会离开。

作为超市管理员,你可以在顾客到来之前重新调整商品的顺序,以便尽可能多地出售商品。当第一个顾客进入后,商品位置不能再调整。目标是计算在最优调整下,最多可以卖出多少件商品。

输入变量说明

  • n:货物架的格子数。
  • m:顾客想要购买的商品种类数。
  • s:货物架上商品的初始顺序(长度为 n 的字符串)。
  • c:顾客想要购买的商品种类(长度为 m 的字符串)。

示例分析

让我们通过示例来理解问题:

  • 示例 1:

    • 输入: n = 3, m = 4, s = "abc", c = "abcd"
    • 输出: 3
    • 解释: 顾客想要购买 a, b, c, d。货架上有 a, b, c。最优调整下,可以卖出 a, b, c,共 3 件商品。
  • 示例 2:

    • 输入: n = 4, m = 2, s = "abbc", c = "bb"
    • 输出: 2
    • 解释: 顾客想要购买 b。货架上有 a, b, b, c。最优调整下,可以卖出 2 个 b
  • 示例 3:

    • 输入: n = 5, m = 4, s = "bcdea", c = "abcd"
    • 输出: 4
    • 解释: 顾客想要购买 a, b, c, d。货架上有 b, c, d, e, a。最优调整下,可以卖出 a, b, c, d,共 4 件商品。

算法思路

为了在最优调整下尽可能多地卖出商品,我们需要:

  1. 统计货架上每种商品的数量
  2. 统计顾客想要购买的每种商品的数量
  3. 计算每种商品在货架上的数量与顾客需求的数量之间的最小值,即每种商品最多可以卖出的数量。
  4. 将所有商品的最大可卖出数量相加,得到最终结果。

图解

假设输入为 n = 5, m = 4, s = "bcdea", c = "abcd"

  • 货架上的商品:b, c, d, e, a
  • 顾客想要的商品:a, b, c, d

统计货架上每种商品的数量:

  • a: 1
  • b: 1
  • c: 1
  • d: 1
  • e: 1

统计顾客想要购买每种商品的数量:

  • a: 1
  • b: 1
  • c: 1
  • d: 1

计算每种商品最多可以卖出的数量:

  • a: min(1, 1) = 1
  • b: min(1, 1) = 1
  • c: min(1, 1) = 1
  • d: min(1, 1) = 1

总销售量:1 + 1 + 1 + 1 = 4

代码详解

import java.util.HashMap;

public class Main {
    public static int solution(int n, int m, String s, String c) {
        // 统计货架上每种商品的数量
        HashMap<Character, Integer> shelfCount = new HashMap<>();
        for (char item : s.toCharArray()) {
            shelfCount.put(item, shelfCount.getOrDefault(item, 0) + 1);
        }

        // 统计顾客想要的商品种类
        HashMap<Character, Integer> customerCount = new HashMap<>();
        for (char item : c.toCharArray()) {
            customerCount.put(item, customerCount.getOrDefault(item, 0) + 1);
        }

        // 计算最多能卖出的商品数量
        int totalSales = 0;
        for (char item : customerCount.keySet()) {
            if (shelfCount.containsKey(item)) {
                totalSales += Math.min(shelfCount.get(item), customerCount.get(item));
            }
        }

        return totalSales;
    }

    public static void main(String[] args) {
        // 测试样例
        System.out.println(solution(3, 4, "abc", "abcd") == 3); // 输出: true
        System.out.println(solution(4, 2, "abbc", "bb") == 2);   // 输出: true
        System.out.println(solution(5, 4, "bcdea", "abcd") == 4); // 输出: true
    }
}
  • 统计货架上的商品数量:

    • 使用 HashMap 记录每种商品在货架上的数量。
    • 遍历字符串 s,将每种商品的数量存入 shelfCount
  • 统计顾客想要的商品种类:

    • 同样使用 HashMap 记录每种商品在顾客需求中的数量。
    • 遍历字符串 c,将每种商品的需求数量存入 customerCount
  • 计算总销售量:

    • 遍历 customerCount 中的每种商品。
    • 对于每种商品,检查货架上是否存在该商品。
    • 如果存在,计算货架上数量与顾客需求数量的最小值,并加到 totalSales 中。
  • 返回结果:

    • 返回 totalSales,即最多可以卖出的商品数量。

知识点总结

  1. HashMap 的使用:

    • HashMap 是 Java 中常用的数据结构,用于存储键值对。
    • getOrDefault 方法可以简化代码,避免显式地检查键是否存在。
  2. 字符串遍历:

    • 使用 toCharArray() 方法将字符串转换为字符数组,方便遍历。
  3. 字符与字符串处理:

    • 字符用 char 类型表示,字符串用 String 类型表示。
    • 字符与字符串之间的转换可以通过 String 类的构造方法实现。
  4. 时间复杂度:

    • 本算法的时间复杂度为 O(n + m),其中 n 是货架上的商品数量,m 是顾客想要的商品种类数。
  5. 空间复杂度:

    • 使用了两个 HashMap,空间复杂度为 O(n + m)。

学习建议

  1. 理解数据结构:

    • 深入理解 HashMap 的工作原理及其常用方法。
    • 掌握其他数据结构(如 ArrayList, LinkedList, Set 等)的使用场景。
  2. 练习字符串操作:

    • 多做字符串相关的练习题,熟悉字符串的各种操作方法。
    • 理解字符串与字符数组之间的转换。
  3. 分析问题:

    • 学会分析问题的本质,找到问题的关键点。
    • 尝试将复杂问题分解成更小的子问题。
  4. 动手实践:

    • 多写代码,尝试不同的算法和数据结构。
    • 尝试自己实现算法,并进行调试和优化。
  5. 学习资源:

    • 阅读经典算法