The Leetcode problem "People Whose List of Favorite Companies Is Not a Subset of Another List" asks you to process a list where each person has a list of their favorite companies. You are to find all people whose list of favorite companies is not a subset of any other person's list.
More formally: Given a list favoriteCompanies
where favoriteCompanies[i]
is a list of strings representing the favorite companies of the i
-th person, return the indices of all people whose list is not a subset of any other person's list. The result can be in any order.
At first glance, the problem seems to require comparing each person's list to every other person's list to check if it's a subset. This would mean, for every person, checking all other people and performing a subset check. This is a classic brute-force approach.
However, this can be inefficient, especially if there are many people or large lists. We want to optimize the subset checking. Since each list contains unique companies, and company names are strings, we can use sets to leverage fast subset operations. We can also consider ways to avoid unnecessary comparisons, such as skipping comparisons for lists of smaller size, or pre-processing the data.
The key insight is to use set operations for subset checking and to minimize redundant work by only comparing relevant pairs.
We approach the problem step-by-step:
issubset
or equivalent operation in O(1) for each comparison (on average).This approach is clean and leverages data structures (sets) for efficient subset checking.
Suppose favoriteCompanies = [["leetcode","google","facebook"], ["google","microsoft"], ["google","facebook"], ["google"], ["amazon"]]
.
Final answer: indices [0,1,4]
.
class Solution:
def peopleIndexes(self, favoriteCompanies):
n = len(favoriteCompanies)
sets = [set(companies) for companies in favoriteCompanies]
res = []
for i in range(n):
is_subset = False
for j in range(n):
if i != j and sets[i].issubset(sets[j]):
is_subset = True
break
if not is_subset:
res.append(i)
return res
class Solution {
public:
vector<int> peopleIndexes(vector<vector<string>>& favoriteCompanies) {
int n = favoriteCompanies.size();
vector<set<string>> sets;
for (auto& companies : favoriteCompanies) {
sets.push_back(set<string>(companies.begin(), companies.end()));
}
vector<int> res;
for (int i = 0; i < n; ++i) {
bool is_subset = false;
for (int j = 0; j < n; ++j) {
if (i != j) {
// check if i's set is subset of j's set
bool subset = true;
for (const string& company : sets[i]) {
if (sets[j].find(company) == sets[j].end()) {
subset = false;
break;
}
}
if (subset) {
is_subset = true;
break;
}
}
}
if (!is_subset) res.push_back(i);
}
return res;
}
};
import java.util.*;
class Solution {
public List<Integer> peopleIndexes(List<List<String>> favoriteCompanies) {
int n = favoriteCompanies.size();
List<Set<String>> sets = new ArrayList<>();
for (List<String> companies : favoriteCompanies) {
sets.add(new HashSet<>(companies));
}
List<Integer> res = new ArrayList<>();
for (int i = 0; i < n; ++i) {
boolean isSubset = false;
for (int j = 0; j < n; ++j) {
if (i != j && sets.get(j).containsAll(sets.get(i))) {
isSubset = true;
break;
}
}
if (!isSubset) res.add(i);
}
return res;
}
}
var peopleIndexes = function(favoriteCompanies) {
let n = favoriteCompanies.length;
let sets = favoriteCompanies.map(list => new Set(list));
let res = [];
for (let i = 0; i < n; ++i) {
let isSubset = false;
for (let j = 0; j < n; ++j) {
if (i !== j) {
// Check if i's set is subset of j's set
let subset = true;
for (let company of sets[i]) {
if (!sets[j].has(company)) {
subset = false;
break;
}
}
if (subset) {
isSubset = true;
break;
}
}
}
if (!isSubset) res.push(i);
}
return res;
};
issubset
are on average O(L), so the overall time complexity remains O(N^2 * L) in the worst case, but the constant factor is improved by using efficient set lookups.The approach is efficient for the input size constraints typically found on Leetcode for this problem.
This problem is a classic example of subset checking between collections. By representing each person's list as a set, we can efficiently check for subset relationships using built-in set operations. The solution iterates over all pairs of people, checks for subset relationships, and collects the indices of people whose lists are not subsets of any other. The approach is simple, leverages the properties of sets, and is both easy to implement and understand.