54
54
55
55
<!-- 这里可写通用的实现逻辑 -->
56
56
57
- ** 方法一:状态压缩 + 记忆化搜索**
57
+ ** 方法一:状态压缩动态规划**
58
+
59
+ 我们注意到,技能清单 ` req_skills ` 的长度不超过 $16$,因此,我们可以用一个长度不超过 $16$ 的二进制数来表示每一种技能是否被掌握。不妨记数组 ` req_skills ` 的长度为 $m$,数组 ` people ` 的长度为 $n$。
60
+
61
+ 我们先将 ` req_skills ` 中的每个技能映射到一个编号,即 $d[ s] $ 表示技能 $s$ 的编号。然后,我们遍历 ` people ` 中的每个人,将其掌握的技能用二进制数表示,即 $p[ i] $ 表示编号为 $i$ 的人掌握的技能。
62
+
63
+ 接下来,我们定义以下三个数组,其中:
64
+
65
+ - 数组 $f[ i] $ 表示掌握技能集合为 $i$ 的最少人数,其中 $i$ 的二进制表示中的每一位为 $1$ 的位置,表示对应的技能被掌握。初始时 $f[ 0] = 0$,其余位置均为无穷大。
66
+ - 数组 $g[ i] $ 表示掌握技能集合为 $i$ 的最少人数时,最后一个人的编号。
67
+ - 数组 $h[ i] $ 表示掌握技能集合为 $i$ 的最少人数时,上一个技能集合状态。
68
+
69
+ 我们在 $[ 0,..2^m-1] $ 的范围内枚举每个技能集合,对于每个技能集合 $i$,我们枚举 ` people ` 中的每个人,如果 $f[ i] + 1 \lt f[ i | p[ j]] $,说明 $f[ i | p[ j]] $ 可以通过 $f[ i] $ 转移得到,此时,我们更新 $f[ i | p[ j]] $ 为 $f[ i] + 1$,并将 $g[ i | p[ j]] $ 更新为 $j$,同时将 $h[ i | p[ j]] $ 更新为 $i$。即当前技能集合状态为 $i | p[ j] $ 时,最后一个人的编号为 $j$,上一个技能集合状态为 $i$。这里符号 $|$ 表示按位或运算。
70
+
71
+ 最后,我们从技能集合 $i=2^m-1$ 开始,找到此时最后一个人的编号 $g[ i] $,将其加入答案中,然后将 $i$ 更新为 $h[ i] $,不断地向前回溯,直到 $i=0$,即可得到最小的必要团队中的人员编号。
72
+
73
+ 时间复杂度 $O(2^m \times n)$,空间复杂度 $O(2^m)$。其中 $m$ 和 $n$ 分别为 ` req_skills ` 和 ` people ` 的长度。
58
74
59
75
<!-- tabs:start -->
60
76
64
80
65
81
``` python
66
82
class Solution :
67
- def smallestSufficientTeam (self , req_skills : List[str ], people : List[List[str ]]) -> List[int ]:
68
- @cache
69
- def dfs (i , state ):
70
- if i == n:
71
- return [] if state == (1 << m) - 1 else None
72
- ans1 = dfs(i + 1 , state)
73
- ans2 = dfs(i + 1 , state | ps[i])
74
- if ans1 is None and ans2 is None :
75
- return None
76
- if ans1 is None :
77
- return [i] + ans2
78
- if ans2 is None :
79
- return ans1
80
- return min (ans1, [i] + ans2, key = len )
81
-
83
+ def smallestSufficientTeam (
84
+ self , req_skills : List[str ], people : List[List[str ]]
85
+ ) -> List[int ]:
82
86
d = {s: i for i, s in enumerate (req_skills)}
83
- m = len (req_skills)
84
- n = len (people)
85
- ps = [0 ] * n
86
- for i, skills in enumerate (people):
87
- for skill in skills:
88
- ps[i] |= 1 << d[skill]
89
- return dfs(0 , 0 )
87
+ m, n = len (req_skills), len (people)
88
+ p = [0 ] * n
89
+ for i, ss in enumerate (people):
90
+ for s in ss:
91
+ p[i] |= 1 << d[s]
92
+ f = [inf] * (1 << m)
93
+ g = [0 ] * (1 << m)
94
+ h = [0 ] * (1 << m)
95
+ f[0 ] = 0
96
+ for i in range (1 << m):
97
+ if f[i] == inf:
98
+ continue
99
+ for j in range (n):
100
+ if f[i] + 1 < f[i | p[j]]:
101
+ f[i | p[j]] = f[i] + 1
102
+ g[i | p[j]] = j
103
+ h[i | p[j]] = i
104
+ i = (1 << m) - 1
105
+ ans = []
106
+ while i:
107
+ ans.append(g[i])
108
+ i = h[i]
109
+ return ans
90
110
```
91
111
92
112
### ** Java**
@@ -95,58 +115,173 @@ class Solution:
95
115
96
116
``` java
97
117
class Solution {
98
- private int m;
99
- private int n;
100
- private int [] ps;
101
- private int [][][] f;
102
- private static final int MX = 100 ;
103
-
104
118
public int [] smallestSufficientTeam (String [] req_skills , List<List<String > > people ) {
105
- m = req_skills. length;
106
- n = people. size();
107
- ps = new int [n];
108
- f = new int [n][1 << m][];
109
119
Map<String , Integer > d = new HashMap<> ();
120
+ int m = req_skills. length;
121
+ int n = people. size();
110
122
for (int i = 0 ; i < m; ++ i) {
111
123
d. put(req_skills[i], i);
112
124
}
125
+ int [] p = new int [n];
113
126
for (int i = 0 ; i < n; ++ i) {
114
- for (String skill : people. get(i)) {
115
- ps [i] |= 1 << d. get(skill );
127
+ for (var s : people. get(i)) {
128
+ p [i] |= 1 << d. get(s );
116
129
}
117
130
}
118
- return dfs(0 , 0 );
131
+ int [] f = new int [1 << m];
132
+ int [] g = new int [1 << m];
133
+ int [] h = new int [1 << m];
134
+ final int inf = 1 << 30 ;
135
+ Arrays . fill(f, inf);
136
+ f[0 ] = 0 ;
137
+ for (int i = 0 ; i < 1 << m; ++ i) {
138
+ if (f[i] == inf) {
139
+ continue ;
140
+ }
141
+ for (int j = 0 ; j < n; ++ j) {
142
+ if (f[i] + 1 < f[i | p[j]]) {
143
+ f[i | p[j]] = f[i] + 1 ;
144
+ g[i | p[j]] = j;
145
+ h[i | p[j]] = i;
146
+ }
147
+ }
148
+ }
149
+ List<Integer > ans = new ArrayList<> ();
150
+ for (int i = (1 << m) - 1 ; i != 0 ; i = h[i]) {
151
+ ans. add(g[i]);
152
+ }
153
+ return ans. stream(). mapToInt(Integer :: intValue). toArray();
119
154
}
155
+ }
156
+ ```
120
157
121
- private int [] dfs (int i , int state ) {
122
- if (i == n) {
123
- return state == (1 << m) - 1 ? new int [0 ] : add(new int[0 ], MX );
158
+ ### ** C++**
159
+
160
+ ``` cpp
161
+ class Solution {
162
+ public:
163
+ vector<int > smallestSufficientTeam(vector<string >& req_skills, vector<vector<string >>& people) {
164
+ unordered_map<string, int> d;
165
+ int m = req_skills.size(), n = people.size();
166
+ for (int i = 0; i < m; ++i) {
167
+ d[ req_skills[ i]] = i;
168
+ }
169
+ int p[ n] ;
170
+ memset(p, 0, sizeof(p));
171
+ for (int i = 0; i < n; ++i) {
172
+ for (auto& s : people[ i] ) {
173
+ p[ i] |= 1 << d[ s] ;
174
+ }
124
175
}
125
- if (f[i][state] != null ) {
126
- return f[i][state];
176
+ int f[ 1 << m] ;
177
+ int g[ 1 << m] ;
178
+ int h[ 1 << m] ;
179
+ memset(f, 63, sizeof(f));
180
+ f[ 0] = 0;
181
+ for (int i = 0; i < 1 << m; ++i) {
182
+ if (f[ i] == 0x3f3f3f3f) {
183
+ continue;
184
+ }
185
+ for (int j = 0; j < n; ++j) {
186
+ if (f[ i] + 1 < f[ i | p[ j]] ) {
187
+ f[ i | p[ j]] = f[ i] + 1;
188
+ g[ i | p[ j]] = j;
189
+ h[ i | p[ j]] = i;
190
+ }
191
+ }
127
192
}
128
- int [] ans1 = dfs(i + 1 , state);
129
- int [] ans2 = dfs(i + 1 , state | ps[i]);
130
- if (ans1. length > 0 && ans1[0 ] == MX && ans2. length > 0 && ans2[0 ] == MX ) {
131
- return f[i][state] = ans1;
193
+ vector<int > ans;
194
+ for (int i = (1 << m) - 1; i; i = h[ i] ) {
195
+ ans.push_back(g[ i] );
132
196
}
133
- if (ans1. length > 0 && ans1[0 ] == MX ) {
134
- return f[i][state] = add(ans2, i);
197
+ return ans;
198
+ }
199
+ };
200
+ ```
201
+
202
+ ### **Go**
203
+
204
+ ```go
205
+ func smallestSufficientTeam(req_skills []string, people [][]string) (ans []int) {
206
+ d := map[string]int{}
207
+ for i, s := range req_skills {
208
+ d[s] = i
209
+ }
210
+ m, n := len(req_skills), len(people)
211
+ p := make([]int, n)
212
+ for i, ss := range people {
213
+ for _, s := range ss {
214
+ p[i] |= 1 << d[s]
215
+ }
216
+ }
217
+ const inf = 1 << 30
218
+ f := make([]int, 1<<m)
219
+ g := make([]int, 1<<m)
220
+ h := make([]int, 1<<m)
221
+ for i := range f {
222
+ f[i] = inf
223
+ }
224
+ f[0] = 0
225
+ for i := range f {
226
+ if f[i] == inf {
227
+ continue
228
+ }
229
+ for j := 0; j < n; j++ {
230
+ if f[i]+1 < f[i|p[j]] {
231
+ f[i|p[j]] = f[i] + 1
232
+ g[i|p[j]] = j
233
+ h[i|p[j]] = i
234
+ }
235
+ }
236
+ }
237
+ for i := 1<<m - 1; i != 0; i = h[i] {
238
+ ans = append(ans, g[i])
239
+ }
240
+ return
241
+ }
242
+ ```
243
+
244
+ ### ** TypeScript**
245
+
246
+ ``` ts
247
+ function smallestSufficientTeam(
248
+ req_skills : string [],
249
+ people : string [][],
250
+ ): number [] {
251
+ const d: Map <string , number > = new Map ();
252
+ const m = req_skills .length ;
253
+ const n = people .length ;
254
+ for (let i = 0 ; i < m ; ++ i ) {
255
+ d .set (req_skills [i ], i );
256
+ }
257
+ const p: number [] = new Array (n ).fill (0 );
258
+ for (let i = 0 ; i < n ; ++ i ) {
259
+ for (const s of people [i ]) {
260
+ p [i ] |= 1 << d .get (s )! ;
135
261
}
136
- if (ans2. length > 0 && ans2[0 ] == MX ) {
137
- return f[i][state] = ans1;
262
+ }
263
+ const inf = 1 << 30 ;
264
+ const f: number [] = new Array (1 << m ).fill (inf );
265
+ const g: number [] = new Array (1 << m ).fill (0 );
266
+ const h: number [] = new Array (1 << m ).fill (0 );
267
+ f [0 ] = 0 ;
268
+ for (let i = 0 ; i < 1 << m ; ++ i ) {
269
+ if (f [i ] === inf ) {
270
+ continue ;
138
271
}
139
- if (ans1. length < ans2. length + 1 ) {
140
- return f[i][state] = ans1;
272
+ for (let j = 0 ; j < n ; ++ j ) {
273
+ if (f [i ] + 1 < f [i | p [j ]]) {
274
+ f [i | p [j ]] = f [i ] + 1 ;
275
+ g [i | p [j ]] = j ;
276
+ h [i | p [j ]] = i ;
277
+ }
141
278
}
142
- return f[i][state] = add(ans2, i);
143
279
}
144
-
145
- private int [] add (int [] nums , int x ) {
146
- int [] copy = Arrays . copyOf(nums, nums. length + 1 );
147
- copy[copy. length - 1 ] = x;
148
- return copy;
280
+ const ans: number [] = [];
281
+ for (let i = (1 << m ) - 1 ; i ; i = h [i ]) {
282
+ ans .push (g [i ]);
149
283
}
284
+ return ans ;
150
285
}
151
286
```
152
287
0 commit comments