2023-04-08 LeetCode每日一题(最小的必要团队)

2023-04-08每日一题

一、题目编号

1125. 最小的必要团队

二、题目链接

https://leetcode.cn/problems/smallest-sufficient-team/

三、题目描述

作为项目经理,你规划了一份需求的技能清单 req_skills,并打算从备选人员名单 people 中选出些人组成一个「必要团队」( 编号为 i 的备选人员 people[i] 含有一份该备选人员掌握的技能列表)。

所谓「必要团队」,就是在这个团队中,对于所需求的技能列表 req_skills 中列出的每项技能,团队中至少有一名成员已经掌握。可以用每个人的编号来表示团队中的成员:

例如,团队 team = [0, 1, 3] 表示掌握技能分别为 people[0],people[1],和 people[3] 的备选人员。
请你返回 任一 规模最小的必要团队,团队成员用人员编号表示。你可以按 任意顺序 返回答案,题目数据保证答案存在。

四、解题代码

class Solution {
    unordered_map<string, int> index;
public:
    vector<int> smallestSufficientTeam(vector<string>& req_skills, vector<vector<string>>& people) {
        int n = req_skills.size();
        int m = people.size();
        for(int i = 0; i < n; ++i){
            index[ req_skills[i] ] = i;
        }
        vector<vector<int>> dp(1 << n);
        for(int i = 0; i < m; ++i){
            int cur_skill = 0;
            for(int j = 0; j < people[i].size(); ++j){
                cur_skill |= (1 << index[people[i][j]]);
            }
            for(int prev = 0; prev < (1 << n); ++prev){
                if(prev > 0 && dp[prev].size() == 0){
                    continue;
                }
                int comb = prev | cur_skill;
                if(comb == prev){
                    continue;
                }
                if(dp[comb].size() == 0 || dp[prev].size() + 1 < dp[comb].size()) {
                    dp[comb] = dp[prev];
                    dp[comb].push_back(i);
                }
            }
        }
    return dp[(1 << n) - 1];
    }
};

五、解题思路

(1)首先我们将每一个技能所对应的数组标号用哈希表进行标记起来。我们用2进制数字来表示技能,比如一个技能java在数组中位置是0,则1<<0则代表具备该技能。

(2)我们用一个包含1 << n的长度的二维数组,来分别存储不同情况下的最小人员。

(3)接下来运用动态规划,依次遍历每一个成员,并从0 ~ (1<<n)- 1做为前置情况prev,来更新dp数组。首先用cur_skill通过位运算来计算该成员所拥有的技能用二进制数如何表示。如果prev>0(表示已经修行了技能)并且dp[prev].size() == 0(表示此时并不存在满足prev情况的人员分配),则跳过该情况判断。接下来取prev 和 cur_skill的并集 comb,如果comb与prev相同,则表示该人员对于prev是多余人员,直接跳过剩下的判断。之后判断,如果没有comb情况下的人员分配,则更新该人员分配,如果新的人员分配少于旧的人员分配,则更新人员分配。

(4)最后返回全技能拥有的人员分配。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值