1125.最小的必要团队
题目描述
你规划了一个技能清单skills,准备从备选人员中选择,
给了一个人员名单列表people,其中元素people[i]表示第i个人具备的技能。
提示:
- skills中的元素互不相同
- people[i]中的技能都在skills范围内
- 技能列表长满足 1到16
f1-记忆化搜索+状态压缩 |
基本分析
- 技能的数量最大为16,暗示什么?可以用一个长度不超过16的二进制数表示每个技能是不是已经有人掌握
- 不添加记忆化和添加记忆化在搜索上的区别在哪?
- 不添加:每个人可以选或者不选,总搜索数为,每次收缩需要O(1)的时间处理
- 添加:重复的状态只需要计算一次,搜索空间为最大人数n*技能对应的状态压缩,总时间复杂度是
- 预处理怎么考虑?(1)因为mask针对的是技能对应的索引,需要一个字典来存技能对应索引的情况;(2)再建立一个列表,遍历人,给出人对应技能索引的情况
- dfs时候的细节怎么考虑?
- 参数一般是遍历情况和状态情况,这里是遍历到的索引i,满足情况mask
- 退出情况是啥?i=n,需要区分mask的情况
- (1) mask == (1<<n)-1, 返回True,[]
- (2)mask != (1<<n)-1, False, []
- 内部进行实现的dfs包括哪俩?
- (1) 考虑第i个人的情况
- (2)不考虑第i个人的情况
- 根据第i+1个人的情况,有哪些处理方式?
- (1)两个都返回False,返回False,[]
- (2)加不行,不加行->返回 True,lst2
- (3)加行,不加不行-> 返回True,lst1+[i]
- (4)都行,看lst1+[i]和lst2的长度,那个短返回哪个
代码
class Solution: def smallestSufficientTeam(self, req_skills: List[str], people: List[List[str]]) -> List[int]: m = len(req_skills) n = len(people) skill_to_idx = dict() # 建立技能对应m中索引的关系 for i, skill in enumerate(req_skills): skill_to_idx[skill] = i p_mask = [0]*n # 建立人能满足的索引形式 for i, skills in enumerate(people): mask = 0 for skill in skills: mask |= (1<<skill_to_idx[skill]) p_mask[i] = mask @cache def dfs(i, mask): if i == n: if mask == (1<<m)-1: return True, [] else: return False, [] check1, lst1 = dfs(i+1, mask | p_mask[i]) check2, lst2 = dfs(i+1, mask) if not check1 and not check2: return False, [] if not check2: return True, lst1+[i] if not check1: return True, lst2 else: if len(lst1+[i]) < len(lst2): return True, lst1 + [i] else: return True, lst2 return dfs(0, 0)[1]
复杂度
时间:
空间:待确定
总结
- 这里给出的是dfs+状态压缩的代码,后续可以追加dp+状态压缩做法
- dfs内需要判断取不取第i个人的情况
- dfs的返回结果写了2个参数,分别表示后续是否可行,结果列表
- 需要明确为啥考虑i时候,返回值需要lst1+[i]?lst1表示的是后面的最优结果吗?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现