You are given an integer n indicating the number of people in a network.
Each person is labeled from 0 to n - 1.
You are also given a 0-indexed 2D integer array restrictions, where
restrictions[i] = [xi, yi] means that person xi and person yicannot become friends ,**** either directly or indirectly through other people.
Initially, no one is friends with each other. You are given a list of friend requests as a 0-indexed 2D integer array requests, where requests[j] = [uj, vj] is a friend request between person uj and person vj.
A friend request is successful if uj and vj can be friends. Each friend request is processed in the given order (i.e., requests[j] occurs before requests[j + 1]), and upon a successful request, uj and vjbecome direct friends for all future friend requests.
Return _aboolean array _result,where eachresult[j]istrueif thejth _friend request issuccessful or _falseif it is not.
Note: If uj and vj are already direct friends, the request is still
successful.
Input: n =3, restrictions =[[0,1]], requests =[[0,2],[2,1]] Output:[true,false] Explanation: Request 0: Person 0 and person 2 can be friends, so they become direct friends. Request 1: Person 2 and person 1 cannot be friends since person 0 and person 1 would be indirect friends(1--2--0).
Input: n =3, restrictions =[[0,1]], requests =[[1,2],[0,2]] Output:[true,false] Explanation: Request 0: Person 1 and person 2 can be friends, so they become direct friends. Request 1: Person 0 and person 2 cannot be friends since person 0 and person 1 would be indirect friends(0--2--1).
Input: n =5, restrictions =[[0,1],[1,2],[2,3]], requests =[[0,4],[1,2],[3,1],[3,4]] Output:[true,false,true,false] Explanation: Request 0: Person 0 and person 4 can be friends, so they become direct friends. Request 1: Person 1 and person 2 cannot be friends since they are directly restricted. Request 2: Person 3 and person 1 can be friends, so they become direct friends. Request 3: Person 3 and person 4 cannot be friends since person 0 and person 1 would be indirect friends(0--4--3--1).
We use Union-Find (Disjoint Set Union) to track friend groups. For each request, we check if merging the groups would violate any restriction. If not, we merge; otherwise, we skip. To avoid affecting future requests, we can simulate the merge and roll back if needed.
classSolution {
public: vector<bool> friendRequests(int n, vector<vector<int>>& restrictions, vector<vector<int>>& requests) {
vector<int> parent(n);
iota(parent.begin(), parent.end(), 0);
function<int(int)> find = [&](int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); };
vector<bool> res;
for (auto& req : requests) {
int u = find(req[0]), v = find(req[1]);
bool ok = true;
if (u != v) {
for (auto& r : restrictions) {
int x = find(r[0]), y = find(r[1]);
if ((u == x && v == y) || (u == y && v == x)) {
ok = false; break;
}
}
}
if (ok) {
res.push_back(true);
if (u != v) parent[u] = v;
} else {
res.push_back(false);
}
}
return res;
}
};
import java.util.*;
classSolution {
publicboolean[]friendRequests(int n, int[][] restrictions, int[][] requests) {
int[] parent =newint[n];
for (int i = 0; i < n; ++i) parent[i]= i;
boolean[] res =newboolean[requests.length];
for (int k = 0; k < requests.length; ++k) {
int u = find(parent, requests[k][0]), v = find(parent, requests[k][1]);
boolean ok =true;
if (u != v) {
for (int[] r : restrictions) {
int x = find(parent, r[0]), y = find(parent, r[1]);
if ((u == x && v == y) || (u == y && v == x)) { ok =false; break; }
}
}
if (ok) {
res[k]=true;
if (u != v) parent[u]= v;
} else {
res[k]=false;
}
}
return res;
}
privateintfind(int[] parent, int x) {
if (parent[x]!= x) parent[x]= find(parent, parent[x]);
return parent[x];
}
}
classSolution {
funfriendRequests(n: Int, restrictions: Array<IntArray>, requests: Array<IntArray>): BooleanArray {
val parent = IntArray(n) { it }
val res = BooleanArray(requests.size)
funfind(x: Int): Int {
if (parent[x] != x) parent[x] = find(parent[x])
return parent[x]
}
for ((k, req) in requests.withIndex()) {
val u = find(req[0]); val v = find(req[1])
var ok = trueif (u != v) {
for (r in restrictions) {
val x = find(r[0]); val y = find(r[1])
if ((u == x && v == y) || (u == y && v == x)) { ok = false; break }
}
}
if (ok) {
res[k] = trueif (u != v) parent[u] = v
} else {
res[k] = false }
}
return res
}
}
from typing import List
classSolution:
deffriendRequests(self, n: int, restrictions: List[List[int]], requests: List[List[int]]) -> List[bool]:
parent = list(range(n))
deffind(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
res = []
for u, v in requests:
ru, rv = find(u), find(v)
ok =Trueif ru != rv:
for x, y in restrictions:
rx, ry = find(x), find(y)
if (ru == rx and rv == ry) or (ru == ry and rv == rx):
ok =Falsebreakif ok:
res.append(True)
if ru != rv:
parent[ru] = rv
else:
res.append(False)
return res
impl Solution {
pubfnfriend_requests(n: i32, restrictions: Vec<Vec<i32>>, requests: Vec<Vec<i32>>) -> Vec<bool> {
let n = n asusize;
letmut parent: Vec<usize>= (0..n).collect();
fnfind(parent: &mut Vec<usize>, x: usize) -> usize {
if parent[x] != x { parent[x] = find(parent, parent[x]); }
parent[x]
}
letmut res = Vec::new();
for req in requests.iter() {
let u = find(&mut parent, req[0] asusize);
let v = find(&mut parent, req[1] asusize);
letmut ok =true;
if u != v {
for r in restrictions.iter() {
let x = find(&mut parent, r[0] asusize);
let y = find(&mut parent, r[1] asusize);
if (u == x && v == y) || (u == y && v == x) { ok =false; break; }
}
}
if ok {
res.push(true);
if u != v { parent[u] = v; }
} else {
res.push(false);
}
}
res
}
}
⏰ Time complexity: O(R * K) where R is the number of requests and K is the number of restrictions (since for each request we may check all restrictions).
🧺 Space complexity: O(N) for the union-find structure.