Count Unhappy Friends
Problem
You are given a list of preferences for n friends, where n is always
even.
For each person i, preferences[i] contains a list of friends sorted in the order of preference. In other words, a friend earlier in the list is more preferred than a friend later in the list. Friends in each list are denoted by integers from 0 to n-1.
All the friends are divided into pairs. The pairings are given in a list
pairs, where pairs[i] = [xi, yi] denotes xi is paired with yi and yi
is paired with xi.
However, this pairing may cause some of the friends to be unhappy. A friend
x is unhappy if x is paired with y and there exists a friend u who is paired with v but:
xprefersuovery, anduprefersxoverv.
Return the number of unhappy friends.
Examples
Example 1
Input: n = 4, preferences = [[1, 2, 3], [3, 2, 0], [3, 1, 0], [1, 2, 0]], pairs = [[0, 1], [2, 3]]
Output: 2
Explanation:
Friend 1 is unhappy because:
- 1 is paired with 0 but prefers 3 over 0, and
- 3 prefers 1 over 2.
Friend 3 is unhappy because:
- 3 is paired with 2 but prefers 1 over 2, and
- 1 prefers 3 over 0.
Friends 0 and 2 are happy.
Example 2
Input: n = 2, preferences = [[1], [0]], pairs = [[1, 0]]
Output: 0
Explanation: Both friends 0 and 1 are happy.
Example 3
Input: n = 4, preferences = [[1, 3, 2], [2, 3, 0], [1, 3, 0], [0, 2, 1]], pairs = [[1, 3], [0, 2]]
Output: 4
Constraints
2 <= n <= 500nis even.preferences.length == npreferences[i].length == n - 10 <= preferences[i][j] <= n - 1preferences[i]does not containi.- All values in
preferences[i]are unique. pairs.length == n/2pairs[i].length == 2xi != yi0 <= xi, yi <= n - 1- Each person is contained in exactly one pair.
Solution
Method 1 – Preference Ranking and Pair Simulation
Intuition
A friend is unhappy if they prefer someone else over their current pair, and that someone also prefers them over their own pair. We can use a ranking matrix to quickly check preferences and simulate all possible pairs to find unhappy friends.
Approach
- Build a ranking matrix
rank[i][j]representing how much personiprefers personj(lower is more preferred). - Build a
pairarray wherepair[x] = ymeans x is paired with y. - For each person x, for every person u that x prefers over their pair y:
- If u prefers x over their own pair v, mark x as unhappy.
- Count and return the number of unhappy friends.
Code
C++
class Solution {
public:
int unhappyFriends(int n, vector<vector<int>>& preferences, vector<vector<int>>& pairs) {
vector<vector<int>> rank(n, vector<int>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
rank[i][preferences[i][j]] = j;
vector<int> pair(n);
for (auto& p : pairs) {
pair[p[0]] = p[1];
pair[p[1]] = p[0];
}
int ans = 0;
for (int x = 0; x < n; ++x) {
int y = pair[x];
for (int i = 0; preferences[x][i] != y; ++i) {
int u = preferences[x][i];
int v = pair[u];
if (rank[u][x] < rank[u][v]) {
ans++;
break;
}
}
}
return ans;
}
};
Go
func unhappyFriends(n int, preferences [][]int, pairs [][]int) int {
rank := make([][]int, n)
for i := range rank {
rank[i] = make([]int, n)
for j, v := range preferences[i] {
rank[i][v] = j
}
}
pair := make([]int, n)
for _, p := range pairs {
pair[p[0]] = p[1]
pair[p[1]] = p[0]
}
ans := 0
for x := 0; x < n; x++ {
y := pair[x]
for i := 0; preferences[x][i] != y; i++ {
u := preferences[x][i]
v := pair[u]
if rank[u][x] < rank[u][v] {
ans++
break
}
}
}
return ans
}
Java
class Solution {
public int unhappyFriends(int n, int[][] preferences, int[][] pairs) {
int[][] rank = new int[n][n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
rank[i][preferences[i][j]] = j;
int[] pair = new int[n];
for (int[] p : pairs) {
pair[p[0]] = p[1];
pair[p[1]] = p[0];
}
int ans = 0;
for (int x = 0; x < n; x++) {
int y = pair[x];
for (int i = 0; preferences[x][i] != y; i++) {
int u = preferences[x][i];
int v = pair[u];
if (rank[u][x] < rank[u][v]) {
ans++;
break;
}
}
}
return ans;
}
}
Kotlin
class Solution {
fun unhappyFriends(n: Int, preferences: Array<IntArray>, pairs: Array<IntArray>): Int {
val rank = Array(n) { IntArray(n) }
for (i in 0 until n)
for (j in 0 until n)
rank[i][preferences[i][j]] = j
val pair = IntArray(n)
for (p in pairs) {
pair[p[0]] = p[1]
pair[p[1]] = p[0]
}
var ans = 0
for (x in 0 until n) {
val y = pair[x]
for (i in 0 until n) {
if (preferences[x][i] == y) break
val u = preferences[x][i]
val v = pair[u]
if (rank[u][x] < rank[u][v]) {
ans++
break
}
}
}
return ans
}
}
Python
class Solution:
def unhappyFriends(self, n: int, preferences: list[list[int]], pairs: list[list[int]]) -> int:
rank = [[0]*n for _ in range(n)]
for i in range(n):
for j, v in enumerate(preferences[i]):
rank[i][v] = j
pair = [0]*n
for x, y in pairs:
pair[x] = y
pair[y] = x
ans = 0
for x in range(n):
y = pair[x]
for u in preferences[x]:
if u == y:
break
v = pair[u]
if rank[u][x] < rank[u][v]:
ans += 1
break
return ans
Rust
impl Solution {
pub fn unhappy_friends(n: i32, preferences: Vec<Vec<i32>>, pairs: Vec<Vec<i32>>) -> i32 {
let n = n as usize;
let mut rank = vec![vec![0; n]; n];
for i in 0..n {
for (j, &v) in preferences[i].iter().enumerate() {
rank[i][v as usize] = j;
}
}
let mut pair = vec![0; n];
for p in pairs.iter() {
pair[p[0] as usize] = p[1] as usize;
pair[p[1] as usize] = p[0] as usize;
}
let mut ans = 0;
for x in 0..n {
let y = pair[x];
for &u in preferences[x].iter() {
if u as usize == y { break; }
let v = pair[u as usize];
if rank[u as usize][x] < rank[u as usize][v] {
ans += 1;
break;
}
}
}
ans
}
}
TypeScript
class Solution {
unhappyFriends(n: number, preferences: number[][], pairs: number[][]): number {
const rank = Array.from({length: n}, () => Array(n).fill(0))
for (let i = 0; i < n; ++i)
for (let j = 0; j < n; ++j)
rank[i][preferences[i][j]] = j
const pair = Array(n)
for (const [x, y] of pairs) {
pair[x] = y
pair[y] = x
}
let ans = 0
for (let x = 0; x < n; ++x) {
const y = pair[x]
for (const u of preferences[x]) {
if (u === y) break
const v = pair[u]
if (rank[u][x] < rank[u][v]) {
ans++
break
}
}
}
return ans
}
}
Complexity
- ⏰ Time complexity:
O(n^2)for building the rank matrix and checking all pairs. - 🧺 Space complexity:
O(n^2)for the rank matrix andO(n)for pairs.