问题描述
在一个超市里,有一个包含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
核心逻辑
-
问题拆解:
- 要在调整后尽可能多地售出商品。
- 需要找到一种商品排列,使得顾客顺序找到商品时,中途不被空格子或其他限制阻挡。
- 售出商品后,商品会从货架上移除,货架长度也会动态减少。
-
实现思路:
- 从顾客购买商品的需求列表
c
的尾部开始倒序查找。 - 每次找到匹配的商品,将其从货架
s
中移除。 - 计数器
sold
用于记录已成功售出的商品数量。
- 从顾客购买商品的需求列表
-
代码解析:
-
外层循环:遍历顾客需求列表
c
,按需求从尾到头。 -
内层循环:遍历货架
s
,尝试匹配当前顾客需求的商品。 -
条件匹配:
- 如果找到需求商品,计数器
sold
加一。 - 将匹配到的商品从
s
中移除(通过字符串切片实现)。
- 如果找到需求商品,计数器
-
如果在当前循环中没有匹配到商品,直接跳出循环,进入下一需求的查找。
-
复杂度分析
-
时间复杂度:
- 外层循环运行m次。
- 内层循环最多运行n次。
- 因此,最坏情况下时间复杂度为O(m×n)。
-
空间复杂度:
- 除了输入数据外,额外使用了计数器变量
sold
和少量字符串切片操作,空间复杂度为O(1)。
- 除了输入数据外,额外使用了计数器变量
代码优化方向
当前代码逐个查找和移除匹配项,效率较低。如果对问题进行优化:
-
使用计数替代移除:
- 可以使用一个计数器(如字典或
collections.Counter
)记录货架上的商品种类及数量,避免多次字符串切片操作。
- 可以使用一个计数器(如字典或
-
排序需求列表和货架:
- 在调整货架商品顺序时,按顾客需求的优先级进行排序。
- 然后直接遍历两个有序列表,匹配尽可能多的商品。
以下是优化后的代码实现:
优化代码实现
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)。
- 使用了额外的