超市里的货物架调整 | 豆包MarsCode AI刷题

5 阅读3分钟

问题描述

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

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

  • n:货物架的格子数
  • m:顾客想要购买的商品种类数
  • s:货物架上商品的初始顺序
  • c:顾客想要购买的商品种类

算法解析

def solution(n: int, m: int, s: str, c: str) -> int:
    for i in range(m):  # 遍历顾客的需求列表,从最后一个需求开始
        for j in range(n):  # 遍历货架上的商品
            if s[j] == c[len(c) - i - 1]:  # 检查当前格子是否匹配顾客需求
                sold += 1  # 成功售出商品
                s = s[:j] + s[j + 1:]  # 移除售出的商品
                n -= 1  # 货架长度减少
                break  # 继续下一个需求
    return sold

核心逻辑

  1. 问题拆解

    • 要在调整后尽可能多地售出商品。
    • 需要找到一种商品排列,使得顾客顺序找到商品时,中途不被空格子或其他限制阻挡。
    • 售出商品后,商品会从货架上移除,货架长度也会动态减少。
  2. 实现思路

    • 从顾客购买商品的需求列表 c 的尾部开始倒序查找。
    • 每次找到匹配的商品,将其从货架 s 中移除。
    • 计数器 sold 用于记录已成功售出的商品数量。
  3. 代码解析

    • 外层循环:遍历顾客需求列表 c,按需求从尾到头。

    • 内层循环:遍历货架 s,尝试匹配当前顾客需求的商品。

    • 条件匹配

      • 如果找到需求商品,计数器 sold 加一。
      • 将匹配到的商品从 s 中移除(通过字符串切片实现)。
    • 如果在当前循环中没有匹配到商品,直接跳出循环,进入下一需求的查找。


复杂度分析

  • 时间复杂度

    • 外层循环运行m次。
    • 内层循环最多运行n次。
    • 因此,最坏情况下时间复杂度为O(m×n)。
  • 空间复杂度

    • 除了输入数据外,额外使用了计数器变量 sold 和少量字符串切片操作,空间复杂度为O(1)。

代码优化方向

当前代码逐个查找和移除匹配项,效率较低。如果对问题进行优化:

  1. 使用计数替代移除

    • 可以使用一个计数器(如字典或 collections.Counter)记录货架上的商品种类及数量,避免多次字符串切片操作。
  2. 排序需求列表和货架

    • 在调整货架商品顺序时,按顾客需求的优先级进行排序。
    • 然后直接遍历两个有序列表,匹配尽可能多的商品。

以下是优化后的代码实现:


优化代码实现

from collections import Counter

def optimized_solution(n: int, m: int, s: str, c: str) -> int:
    # 统计货架上商品数量
    stock = Counter(s)
    sold = 0

    # 遍历顾客需求
    for item in c:
        if stock[item] > 0:  # 如果货架上有该商品
            sold += 1
            stock[item] -= 1  # 减少库存
    return sold

优化后的复杂度

  • 时间复杂度

    • 构建 Counter 的复杂度为O(n)。
    • 遍历顾客需求的复杂度为O(m)。
    • 总体时间复杂度为O(n+m),显著优于原实现。
  • 空间复杂度

    • 使用了额外的 Counter 对象,空间复杂度为O(n)。