题目描述
给你一个数组 favoriteCompanies
,其中 favoriteCompanies[i]
是第 i
名用户收藏的公司清单(下标从 0 开始)。
请找出不是其他任何人收藏的公司清单的子集的收藏清单,并返回该清单下标。下标需要按升序排列。
示例 1:
输入:favoriteCompanies = [["leetcode","google","facebook"],["google","microsoft"],["google","facebook"],["google"],["amazon"]]
输出:[0,1,4]
解释:
favoriteCompanies[2]=["google","facebook"] 是 favoriteCompanies[0]=["leetcode","google","facebook"] 的子集。
favoriteCompanies[3]=["google"] 是 favoriteCompanies[0]=["leetcode","google","facebook"] 和 favoriteCompanies[1]=["google","microsoft"] 的子集。
其余的收藏清单均不是其他任何人收藏的公司清单的子集,因此,答案为 [0,1,4] 。
示例 2:
输入:favoriteCompanies = [["leetcode","google","facebook"],["leetcode","amazon"],["facebook","google"]]
输出:[0,1]
解释:favoriteCompanies[2]=["facebook","google"] 是 favoriteCompanies[0]=["leetcode","google","facebook"] 的子集,因此,答案为 [0,1] 。
示例 3:
输入:favoriteCompanies = [["leetcode"],["google"],["facebook"],["amazon"]]
输出:[0,1,2,3]
提示:
1 <= favoriteCompanies.length <= 100
1 <= favoriteCompanies[i].length <= 500
1 <= favoriteCompanies[i][j].length <= 20
favoriteCompanies[i]
中的所有字符串 各不相同 。
- 用户收藏的公司清单也 各不相同 ,也就是说,即便我们按字母顺序排序每个清单,
favoriteCompanies[i] != favoriteCompanies[j]
仍然成立。
- 所有字符串仅包含小写英文字母。
解法
方法一:哈希表
我们可以将每个公司映射到一个唯一的整数,然后对于每个人,我们将他们收藏的公司转换为整数集合,最后判断是否存在一个人的收藏公司是另一个人的子集。
时间复杂度 $(n \times m \times k + n^2 \times m)$,空间复杂度 $O(n \times m)$。其中 $n$ 和 $m$ 分别是 favoriteCompanies
的长度和每个公司清单的平均长度,而 $k$ 是每个公司的平均长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | class Solution:
def peopleIndexes(self, favoriteCompanies: List[List[str]]) -> List[int]:
idx = 0
d = {}
n = len(favoriteCompanies)
nums = [set() for _ in range(n)]
for i, ss in enumerate(favoriteCompanies):
for s in ss:
if s not in d:
d[s] = idx
idx += 1
nums[i].add(d[s])
ans = []
for i in range(n):
if not any(i != j and (nums[i] & nums[j]) == nums[i] for j in range(n)):
ans.append(i)
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 | class Solution {
public List<Integer> peopleIndexes(List<List<String>> favoriteCompanies) {
int n = favoriteCompanies.size();
Map<String, Integer> d = new HashMap<>();
int idx = 0;
Set<Integer>[] nums = new Set[n];
Arrays.setAll(nums, i -> new HashSet<>());
for (int i = 0; i < n; ++i) {
var ss = favoriteCompanies.get(i);
for (var s : ss) {
if (!d.containsKey(s)) {
d.put(s, idx++);
}
nums[i].add(d.get(s));
}
}
List<Integer> ans = new ArrayList<>();
for (int i = 0; i < n; ++i) {
boolean ok = true;
for (int j = 0; j < n && ok; ++j) {
if (i != j && nums[j].containsAll(nums[i])) {
ok = false;
}
}
if (ok) {
ans.add(i);
}
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 | class Solution {
public:
vector<int> peopleIndexes(vector<vector<string>>& favoriteCompanies) {
int n = favoriteCompanies.size();
unordered_map<string, int> d;
int idx = 0;
vector<unordered_set<int>> nums(n);
for (int i = 0; i < n; ++i) {
for (const auto& s : favoriteCompanies[i]) {
if (!d.contains(s)) {
d[s] = idx++;
}
nums[i].insert(d[s]);
}
}
auto check = [](const unordered_set<int>& a, const unordered_set<int>& b) {
for (int x : a) {
if (!b.contains(x)) {
return false;
}
}
return true;
};
vector<int> ans;
for (int i = 0; i < n; ++i) {
bool ok = true;
for (int j = 0; j < n && ok; ++j) {
if (i != j && check(nums[i], nums[j])) {
ok = false;
}
}
if (ok) {
ans.push_back(i);
}
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 | func peopleIndexes(favoriteCompanies [][]string) (ans []int) {
n := len(favoriteCompanies)
d := make(map[string]int)
idx := 0
nums := make([]map[int]struct{}, n)
for i := 0; i < n; i++ {
nums[i] = make(map[int]struct{})
for _, s := range favoriteCompanies[i] {
if _, ok := d[s]; !ok {
d[s] = idx
idx++
}
nums[i][d[s]] = struct{}{}
}
}
check := func(a, b map[int]struct{}) bool {
for x := range a {
if _, ok := b[x]; !ok {
return false
}
}
return true
}
for i := 0; i < n; i++ {
ok := true
for j := 0; j < n && ok; j++ {
if i != j && check(nums[i], nums[j]) {
ok = false
}
}
if ok {
ans = append(ans, i)
}
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 | function peopleIndexes(favoriteCompanies: string[][]): number[] {
const n = favoriteCompanies.length;
const d: Map<string, number> = new Map();
let idx = 0;
const nums: Set<number>[] = Array.from({ length: n }, () => new Set<number>());
for (let i = 0; i < n; i++) {
for (const s of favoriteCompanies[i]) {
if (!d.has(s)) {
d.set(s, idx++);
}
nums[i].add(d.get(s)!);
}
}
const check = (a: Set<number>, b: Set<number>): boolean => {
for (const x of a) {
if (!b.has(x)) {
return false;
}
}
return true;
};
const ans: number[] = [];
for (let i = 0; i < n; i++) {
let ok = true;
for (let j = 0; j < n && ok; j++) {
if (i !== j && check(nums[i], nums[j])) {
ok = false;
}
}
if (ok) {
ans.push(i);
}
}
return ans;
}
|