[Swift]LeetCode1125. 最小的必要團隊 | Smallest Sufficient Team

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-sbggvqkq-kw.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

In a project, you have a list of required skills req_skills, and a list of people.  The i-th person people[i] contains a list of skills that person has.java

Consider a sufficient team: a set of people such that for every required skill in req_skills, there is at least one person in the team who has that skill.  We can represent these teams by the index of each person: for example, team = [0, 1, 3] represents the people with skills people[0]people[1], and people[3].node

Return any sufficient team of the smallest possible size, represented by the index of each person.react

You may return the answer in any order.  It is guaranteed an answer exists. git

Example 1:github

Input: req_skills = ["java","nodejs","reactjs"], people = [["java"],["nodejs"],["nodejs","reactjs"]]
Output: [0,2]

Example 2:微信

Input: req_skills = ["algorithms","math","java","reactjs","csharp","aws"], people = [["algorithms","math","java"],["algorithms","math","reactjs"],["java","csharp","aws"],["reactjs","csharp"],["csharp","math"],["aws","java"]]
Output: [1,2] 

Constraints:app

  • 1 <= req_skills.length <= 16
  • 1 <= people.length <= 60
  • 1 <= people[i].length, req_skills[i].length, people[i][j].length <= 16
  • Elements of req_skills and people[i] are (respectively) distinct.
  • req_skills[i][j], people[i][j][k] are lowercase English letters.
  • It is guaranteed a sufficient team exists.

做爲項目經理,你規劃了一份需求的技能清單 req_skills,並打算從備選人員名單 people 中選出些人組成一個「必要團隊」( 編號爲 i 的備選人員 people[i] 含有一份該備選人員掌握的技能列表)。ide

所謂「必要團隊」,就是在這個團隊中,對於所需求的技能列表 req_skills 中列出的每項技能,團隊中至少有一名成員已經掌握。ui

咱們能夠用每一個人的編號來表示團隊中的成員:例如,團隊 team = [0, 1, 3] 表示掌握技能分別爲 people[0]people[1],和 people[3] 的備選人員。

請你返回 任一 規模最小的必要團隊,團隊成員用人員編號表示。你能夠按任意順序返回答案,本題保證答案存在。 

示例 1:

輸入:req_skills = ["java","nodejs","reactjs"], people = [["java"],["nodejs"],["nodejs","reactjs"]]
輸出:[0,2]

示例 2:

輸入:req_skills = ["algorithms","math","java","reactjs","csharp","aws"], people = [["algorithms","math","java"],["algorithms","math","reactjs"],["java","csharp","aws"],["reactjs","csharp"],["csharp","math"],["aws","java"]]
輸出:[1,2] 

提示:

  • 1 <= req_skills.length <= 16
  • 1 <= people.length <= 60
  • 1 <= people[i].length, req_skills[i].length, people[i][j].length <= 16
  • req_skills 和 people[i] 中的元素分別各不相同
  • req_skills[i][j], people[i][j][k] 都由小寫英文字母組成
  • 本題保證「必要團隊」必定存在

132ms
 1 class Solution {
 2     func smallestSufficientTeam(_ req_skills: [String], _ people: [[String]]) -> [Int] {
 3         var solution = Set<Int>()
 4         var setPeople = people.map { Set($0) }
 5         var skillToPeopleDict = [String:[Int]]()
 6         
 7         for (i, personSet) in setPeople.enumerated() {
 8             for (j, anotherPersonSet) in setPeople.enumerated() where i != j {
 9                 if personSet.isSubset(of: anotherPersonSet) {
10                     setPeople[i] = []
11                     break
12                 }
13             }
14         }
15         
16         for (i, personSet) in setPeople.enumerated() {
17             for skill in personSet {
18                 skillToPeopleDict[skill] = (skillToPeopleDict[skill] ?? []) + [i]
19             }
20         }
21         
22         return smallestSufficientTeam(req_skills, skillToPeopleDict, setPeople, 0, [], [])
23     }
24     
25     func smallestSufficientTeam(_ skills: [String], 
26                                 _ skillToPeopleDict: [String:[Int]],
27                                 _ people: [Set<String>],
28                                 _ i: Int,
29                                 _ totalSkillsAdded: Set<String>,
30                                 _ soFar: [Int]) -> [Int] {
31         if i >= skills.count { return Array(soFar) }
32         
33         let nextSkill = skills[i]
34         
35         if totalSkillsAdded.contains(nextSkill) {
36             return smallestSufficientTeam(skills, skillToPeopleDict, people, i+1, totalSkillsAdded, soFar)   
37         }
38         
39         var solution = [Int]()
40         
41         for person in skillToPeopleDict[nextSkill] ?? [] {
42             let personSkills = people[person]
43             let next = smallestSufficientTeam(skills, 
44                                               skillToPeopleDict, 
45                                               people, 
46                                               i+1, 
47                                               totalSkillsAdded.union(personSkills),
48                                               soFar + [person])   
49             
50             if !next.isEmpty {
51                 if solution.isEmpty {
52                     solution = next
53                 } else if next.count < solution.count {
54                     solution = next
55                 }
56             }
57         }
58         
59         return solution
60     }
61 }

156ms

 1 class Solution {
 2     func smallestSufficientTeam(_ req_skills: [String], _ people: [[String]]) -> [Int] {
 3         let req_skills_len = req_skills.count, people_len = people.count
 4         var map = [String: Int]()
 5         for i in 0..<req_skills_len {
 6             map[req_skills[i]] = i
 7         }
 8         var dp = [Int: [Int]]()
 9         dp[0] = [Int]()
10 
11         for i in 0..<people_len {
12             var his_skill = 0
13             for skill in people[i] {
14                 if map[skill] != nil {
15                     his_skill |= 1<<map[skill]!
16                 }
17             }
18             for (skill_set, need) in dp {
19                 let with_him = skill_set | his_skill
20                 if with_him == skill_set { continue }
21                 if dp[with_him] == nil || dp[with_him]!.count > need.count+1 {
22                     var sets = need
23                     sets.append(i)
24                     dp[with_him] = sets
25                 }
26             }
27         }
28         return dp[1<<req_skills_len - 1, default: [Int]()]
29     }
30 }

180ms

 1 class Solution {
 2     func smallestSufficientTeam(_ req_skills: [String], _ people: [[String]]) -> [Int] {
 3         let n = req_skills.count 
 4         let m = people.count 
 5         var dict = [String: Int]()
 6         for i in 0..<req_skills.count {
 7             let skill = req_skills[i]
 8             dict[skill] = i
 9         }
10         
11         var dp = [Int: [Int]]()
12         dp[0] = [Int]()
13         
14         for (idx, skills) in people.enumerated() {
15             var his_skill = 0
16             for skill in skills {
17                 his_skill |= 1 << dict[skill]!
18             }
19             
20             for (skill_set, need) in dp {
21                 let with_him = skill_set | his_skill
22                 if with_him == skill_set { continue }
23                 if dp[with_him] == nil || dp[with_him]!.count > need.count + 1 {
24                     dp[with_him] = need + [idx]
25                 }
26             }
27         }
28         return dp[(1<<n) - 1]!
29     }
30 }

296ms

 1 class Solution {
 2     struct Team {
 3         public let people: [Int]
 4           public let required: Set<String>
 5 
 6         init(required: [String]) {
 7              self.people = []
 8                self.required = Set<String>(required)
 9         }
10 
11         init(team: Team, adding idx: Int, with skills: [String]) {
12             self.people = team.people + [ idx ]
13                self.required = team.required.subtracting(skills)
14         }
15     }
16 
17     private func completeTeam(_ team: Team, _ people: [[String]], _ bySkill: [String:[Int]]) -> Team? {
18         guard let skill = team.required.first else {
19             return team
20         }
21         guard let withSkill = bySkill[skill] else {
22             return nil
23         }
24 
25         var bestTeam: Team?
26         var requiredUsed = Set<Set<String>>()
27         for idx in withSkill {
28             let tmpTeam = Team(team: team, adding: idx, with: people[idx])
29             if requiredUsed.contains(tmpTeam.required) {
30                 continue
31             }
32             requiredUsed.insert(tmpTeam.required)
33             
34             guard let tmpResult = self.completeTeam(tmpTeam, people, bySkill) else {
35                 continue
36             }
37             if bestTeam == nil || bestTeam!.people.count > tmpResult.people.count {
38                 bestTeam = tmpResult
39             }
40         }
41         return bestTeam
42     }
43 
44     func smallestSufficientTeam(_ req_skills: [String], _ people: [[String]]) -> [Int] {
45         guard req_skills.count > 0 && people.count > 0 else {
46             return []
47         }
48 
49         var bySkill = [String:[Int]]()
50         let team = Team(required: req_skills)
51         for (idx, skills) in people.enumerated() {
52             for skill in team.required.intersection(skills) {
53                   bySkill[skill, default: []].append(idx)
54             }
55         }
56 
57         if let result = self.completeTeam(team, people, bySkill) {
58             return result.people
59         } else {
60             return []
61         }
62     }
63 }

Runtime: 652 ms

Memory Usage: 82.7 MB
 1 class Solution {
 2     func smallestSufficientTeam(_ req_skills: [String], _ people: [[String]]) -> [Int] {
 3         var inf:Int = 0x3f3f3f3f
 4         let m:Int = req_skills.count
 5         let n:Int = people.count
 6         var all:Int = 1 << m
 7         var skill_id:[String:Int] = [String:Int]()
 8         var k:Int = 0
 9         for skill in req_skills
10         {
11             skill_id[skill] = k
12             k += 1
13         }
14         var skillset:[Int] = [Int](repeating:0,count:n)
15         for i in 0..<n
16         {
17             var st:Int = 0
18             for skill in people[i]
19             {
20                 st |= 1 << skill_id[skill]!
21             }
22             skillset[i] = st
23         }
24         var dp:[[Int]] = [[Int]](repeating:[Int](repeating:inf,count:all),count:n + 1)
25         var last:[[Int]] = [[Int]](repeating:[Int](repeating:0,count:all),count:n + 1)
26         dp[0][0] = 0
27         for i in 1...n
28         {
29             for j in 0..<all
30             {
31                 if dp[i][j] > dp[i - 1][j]
32                 {
33                     dp[i][j] = dp[i - 1][j]
34                     last[i][j] = j
35                 }
36                 if dp[i - 1][j] + 1 < dp[i][j | skillset[i - 1]]
37                 {
38                     dp[i][j | skillset[i - 1]] = dp[i - 1][j] + 1
39                     last[i][j | skillset[i - 1]] = j
40                 }
41             }
42         }
43         var i:Int = n
44         var j:Int = all - 1
45         var res:[Int] = [Int]()
46         while(i != 0)
47         {
48             if last[i][j] != j
49             {
50                 res.insert(i - 1,at:0)
51             }
52             j = last[i][j]
53             i -= 1
54         }
55         return res      
56     }
57 }
相關文章
相關標籤/搜索