The "Leetcodify Similar Friends" problem provides you with a list of users, each having a list of solved LeetCode problems. Your task is to find all pairs of users who are "Leetcodify similar friends." Two users are considered Leetcodify similar friends if:
k
common problems (where k
is a given integer).k
.
The output should be a list of all unique user pairs who meet the similarity condition.
To solve this problem, we first need to compare every pair of users to determine if they share at least k
solved problems. The naive approach would be to check every possible pair and count the intersection of their solved problem lists.
However, since the number of users and problems could be large, this brute-force method may be inefficient. We need to think about optimizing the way we compare users. By representing each user's solved problems as a set, we can quickly compute intersections. Additionally, to avoid duplicate pairs, we can ensure we only consider each unordered pair once (e.g., by always pairing user1
with user2
where user1 < user2
).
The key is to balance between correctness (finding all valid pairs) and efficiency (not recalculating intersections or comparing users unnecessarily).
Here's how we can approach the problem step by step:
n
users, there are n * (n - 1) / 2
unique pairs.k
:
This approach is efficient and straightforward, leveraging set operations to speed up intersection checks.
Suppose we have the following input:
Brute-force approach:
m
problems, and there are n
users, time is O(n2 * m).k
early.
The key insight is to use set intersections for efficient comparison. By iterating over all unique user pairs and checking whether their solved problems overlap by at least k
, we can quickly find all "Leetcodify similar friends." The solution is elegant because it leverages built-in data structures for speed, avoids redundant comparisons, and ensures output uniqueness.
def leetcodify_similar_friends(users, k):
# users: List of [username, [problem ids]]
name_to_set = {name: set(problems) for name, problems in users}
names = [name for name, _ in users]
result = []
n = len(names)
for i in range(n):
for j in range(i + 1, n):
name1, name2 = names[i], names[j]
if len(name_to_set[name1] & name_to_set[name2]) >= k:
result.append((name1, name2))
return result
#include <vector>
#include <string>
#include <unordered_set>
using namespace std;
vector<pair<string, string>> leetcodifySimilarFriends(
vector<pair<string, vector<int>>>& users, int k) {
int n = users.size();
vector<unordered_set<int>> sets;
vector<string> names;
for (auto& user : users) {
names.push_back(user.first);
sets.push_back(unordered_set<int>(user.second.begin(), user.second.end()));
}
vector<pair<string, string>> result;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
int common = 0;
for (int p : sets[i]) {
if (sets[j].count(p)) {
++common;
if (common >= k) break;
}
}
if (common >= k) {
result.push_back({names[i], names[j]});
}
}
}
return result;
}
import java.util.*;
public class LeetcodifySimilarFriends {
public static List<List<String>> leetcodifySimilarFriends(
List<Pair<String, List<Integer>>> users, int k) {
int n = users.size();
List<String> names = new ArrayList<>();
List<Set<Integer>> sets = new ArrayList<>();
for (Pair<String, List<Integer>> user : users) {
names.add(user.getKey());
sets.add(new HashSet<>(user.getValue()));
}
List<List<String>> result = new ArrayList<>();
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
int common = 0;
for (int p : sets.get(i)) {
if (sets.get(j).contains(p)) {
++common;
if (common >= k) break;
}
}
if (common >= k) {
result.add(Arrays.asList(names.get(i), names.get(j)));
}
}
}
return result;
}
}
// Helper Pair class for demonstration
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) { this.key = key; this.value = value; }
public K getKey() { return key; }
public V getValue() { return value; }
}
function leetcodifySimilarFriends(users, k) {
// users: Array of [name, [problem ids]]
const nameToSet = new Map();
const names = [];
for (const [name, problems] of users) {
nameToSet.set(name, new Set(problems));
names.push(name);
}
const result = [];
for (let i = 0; i < names.length; ++i) {
for (let j = i + 1; j < names.length; ++j) {
const set1 = nameToSet.get(names[i]);
const set2 = nameToSet.get(names[j]);
let common = 0;
for (const p of set1) {
if (set2.has(p)) {
common += 1;
if (common >= k) break;
}
}
if (common >= k) {
result.push([names[i], names[j]]);
}
}
}
return result;
}