题目描述:
给你一个数组 favoriteCompanies ,其中 favoriteCompanies[i] 是第 i 名用户收藏的公司清单(下标从 0 开始)。请找出不是其他任何人收藏的公司清单的子集的收藏清单,并返回该清单下标。下标需要按升序排列。有以下限制:
- 1 <= favoriteCompanies.length <= 100
- 1 <= favoriteCompanies[i].length <= 500
- 1 <= favoriteCompanies[i][j].length <= 20
- favoriteCompanies[i] 中的所有字符串 各不相同 。
- 用户收藏的公司清单也 各不相同 ,也就是说,即便我们按字母顺序排序每个清单, favoriteCompanies[i] != favoriteCompanies[j] 仍然成立。所有字符串仅包含小写英文字母。
题解:
判断集合是否为其他集合的子集,我们记$favoriteCompanies.length$为$n$、记$favoriteCompanies[i].length$为$m$、记$favoriteCompanies[i][j].length$为$k$。我们先按照集合的大小排序,用一个vector<int> ans存一下独立集合(不是任何集合的子集)的index。接着从集合size()最大的那个集合开始遍历,如果其能够在ans中找到一个包含其的集合,那么pass;否则作为新的独立子集加入ans。这么做可行的原因是,ans包含了比当前遍历到的集合size()大的所有集合(对于没有加入$ans$的集合$t$,一定有一个集合$z in ans$,$t$是$z$的子集)。是否为子集的判断用STL的inclueds函数就可以了,按照集合的size()排序用map就可以了,代码如下:
class Solution { public: vector<int> peopleIndexes(vector<vector<string>>& favoriteCompanies) { for (auto& f : favoriteCompanies) { sort(f.begin(), f.end()); } map<int, vector<int>> mapSizeIndex; for (int i = 0; i < favoriteCompanies.size(); i++) { mapSizeIndex[favoriteCompanies[i].size()].push_back(i); } vector<int> ans; for (auto it = mapSizeIndex.rbegin(); it != mapSizeIndex.rend(); it++) { for (auto& p : it->second) { if (it != mapSizeIndex.rbegin() && checkIncludes(favoriteCompanies, ans, p)) continue; ans.push_back(p); } } sort(ans.begin(), ans.end()); return ans; } bool checkIncludes(vector<vector<string>>& fc, vector<int>& ans, int p) { for (auto i : ans) { if (includes(fc[i].begin(), fc[i].end(), fc[p].begin(), fc[p].end())) return true; } return false; } };