H-691. Stickers to Spell Word
class Solution:
def minStickers(self, stickers, target):
# cnt是当前target每个字符出现次数的字典
# res是当前最少需要的stickers数量
# n是target长度
cnt, res, n = collections.Counter(target), float("inf"), len(target)
# dic是当前选中的所有stickers的字符组成的字典, key是字符, value是出现次数
# used是当前使用的stickers的数量
# i是当前正在判断的target的下标(即, 也可以理解为一个指针)
def dfs(dic, used, i):
# 因为res在函数里被赋值, 且不是mutable, 所以需要声明nonlocal
# 详见: https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
nonlocal res
# 如果指针指向第n位, 说明判断结束
if i == n:
res = used
# 如果在判断第i位的时候, 根据此时已经选出来的stickers构造的
# 的dic中, target[i]这个字符的数量已经大于等于cnt中这个字符的数量,
# 我们直接判断target的下一位
elif dic[target[i]] >= cnt[target[i]]:
dfs(dic, used, i + 1)
# 1. 从stickers里面选择一个sticker,
# 如果target[i]存在于此sticker里, 我们用它继续构造
# dic. 接着我们递归调用. 递归出来之后, 记得从dic中
# 删除它.
# 2. 注意入口条件是used < res - 1 因为进入这个循环之后,
# 要么target[i]不在sticker里面, 则进了相当于没进
# 要么target[i]在sticker里面, 此时我们需要把这个sticker加入
# dic里, 然后used + 1, 如果此时used + 1等于res, 那么可以预见,
# 最终通过这条路径选出来的res_2是要大于等于当前res的, 所以
# 我们本来可以不必进入这条路径的.
# 所以我们只允许当used + 1 < res的时候进来.(这样可以少计算很多)
elif used + 1 < res:
for sticker in stickers:
if target[i] in sticker:
for s in sticker:
dic[s] += 1
dfs(dic, used + 1, i + 1)
for s in sticker:
dic[s] -= 1
dfs(collections.defaultdict(int), 0, 0)
return res if res < float("inf") else -1
Last updated
Was this helpful?