Count Unhappy Friends
MedPrompt
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.
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.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach directly translates the problem definition into code without much optimization. We iterate through each person x and check if they are unhappy. To do this, we iterate through every other person u and check if the two conditions for unhappiness are met.
The conditions are:
xprefersuover their current partnery.uprefersxover their current partnerv.
To check these preferences, we need to find the positions of the friends in the preference lists. Since the preference lists are sorted by preference, a smaller index means a higher preference. We can find these positions by linearly scanning the respective preference lists.
Algorithm
- Create an array
pairedWithof sizen. Iterate through thepairslist. For each pair[p1, p2], setpairedWith[p1] = p2andpairedWith[p2] = p1. - Initialize
unhappyCount = 0. - Loop for
xfrom0ton-1:- Let
y = pairedWith[x]. - Initialize a flag
is_x_unhappy = false. - Loop for
ufrom0ton-1:- If
u == x, continue. - Let
v = pairedWith[u]. - To check if
xprefersuovery:- Find
rank_u_for_xandrank_y_for_xby iterating throughpreferences[x].
- Find
- To check if
uprefersxoverv:- Find
rank_x_for_uandrank_v_for_uby iterating throughpreferences[u].
- Find
- If
rank_u_for_x < rank_y_for_xANDrank_x_for_u < rank_v_for_u:- Set
is_x_unhappy = true. - Break the inner loop (over
u).
- Set
- If
- If
is_x_unhappyis true, incrementunhappyCount.
- Let
- Return
unhappyCount.
Walkthrough
First, we need an easy way to find out who is paired with whom. We can pre-process the pairs list into an array, let's call it pairedWith, where pairedWith[i] gives the partner of person i. This takes O(n) time.
Then, the main logic proceeds as follows:
- Initialize a counter for unhappy friends,
unhappyCount, to 0. - Iterate through each person
xfrom0ton-1. - For each
x, find their partnery = pairedWith[x]. - To determine if
xis unhappy, we check against every other personu. - For each potential
u, find their partnerv = pairedWith[u]. - Now, check the two unhappiness conditions:
a.
xprefersuovery: We scanpreferences[x]to find the index (rank) ofuandy. Ifrank_of_u < rank_of_y, this condition is met. This scan takes O(n) time. b.uprefersxoverv: Similarly, we scanpreferences[u]to find the rank ofxandv. Ifrank_of_x < rank_of_v, this condition is met. This scan also takes O(n) time. - If both conditions are true for any
u, we've established thatxis unhappy. We incrementunhappyCountand can immediately stop checking otheru's for the currentx(by breaking the inner loop) and move to the next person.
The total number of unhappy friends is the final value of unhappyCount.
class Solution { private int getRank(int[] preferenceList, int person) { for (int i = 0; i < preferenceList.length; i++) { if (preferenceList[i] == person) { return i; } } return -1; // Should not happen } public int unhappyFriends(int n, int[][] preferences, int[][] pairs) { int[] pairedWith = new int[n]; for (int[] pair : pairs) { pairedWith[pair[0]] = pair[1]; pairedWith[pair[1]] = pair[0]; } int unhappyCount = 0; for (int x = 0; x < n; x++) { int y = pairedWith[x]; int yRankForX = getRank(preferences[x], y); boolean foundCauseForUnhappiness = false; for (int u = 0; u < n; u++) { if (x == u) continue; int uRankForX = getRank(preferences[x], u); if (uRankForX < yRankForX) { // x prefers u over y. Now check if u prefers x over its partner. int v = pairedWith[u]; int xRankForU = getRank(preferences[u], x); int vRankForU = getRank(preferences[u], v); if (xRankForU < vRankForU) { foundCauseForUnhappiness = true; break; } } } if (foundCauseForUnhappiness) { unhappyCount++; } } return unhappyCount; }}Complexity
Time
O(n^3). The outer loop runs `n` times for each person `x`. The inner loop runs `n` times for each potential person `u`. Inside the inner loop, we perform linear scans on preference lists (`preferences[x]` and `preferences[u]`) to find ranks, each taking O(n) time. This results in a total time complexity of O(n * n * n) = O(n^3).
Space
O(n). We use an array `pairedWith` of size `n` to store the pairings.
Trade-offs
Pros
Simple to understand and implement as it directly follows the problem statement.
Low auxiliary space complexity.
Cons
High time complexity, which might be too slow for larger values of
n. Forn = 500,n^3is 125,000,000, which could lead to a 'Time Limit Exceeded' error on some platforms.
Solutions
Solution
class Solution {public int unhappyFriends(int n, int[][] preferences, int[][] pairs) { int[][] d = new int[n][n]; for (int i = 0; i < n; ++i) { for (int j = 0; j < n - 1; ++j) { d[i][preferences[i][j]] = j; } } int[] p = new int[n]; for (var e : pairs) { int x = e[0], y = e[1]; p[x] = y; p[y] = x; } int ans = 0; for (int x = 0; x < n; ++x) { int y = p[x]; int find = 0; for (int i = 0; i < d[x][y]; ++i) { int u = preferences[x][i]; if (d[u][x] < d[u][p[u]]) { find = 1; break; } } ans += find; } return ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.