Given a list of the friendship preferences of n friends, where n is always even.
For each friend i, preferences[i] contains a list of friends ordered from most preferred to least preferred. In other words, a friend appearing earlier in the list is preferred by i over a friend appearing later. Each friend is represented by an integer between 0 and n-1.
All friends are split into pairs, given by the list pairs, where pairs[i] = [xi, yi] means that xi is paired with yi, and yi is paired with xi.
However, this pairing may make some friends unhappy. If x is paired with y and u is paired with v, then x is unhappy if both of the following conditions hold:
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 1 prefers 3 over 0, and - 3 prefers 1 over 2. Friend 3 is unhappy because: - 3 is paired with 2, but 3 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:Friends 0 and 1 are both 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 evenpreferences.length == npreferences[i].length == n - 10 <= preferences[i][j] <= n - 1preferences[i]does not containi- All values in
preferences[i]are distinct pairs.length == n/2pairs[i].length == 2xi != yi0 <= xi, yi <= n - 1- Every friend is included in exactly one pair
Approach#
First, preprocess the input. When querying the preference between two people, we want to provide two people and receive a preference score, but the data supplied by the problem is not convenient for that. We can reorganize it into a two-dimensional array.
# let n = 10;
# let preferences = vec![vec![3]];
let n = n as usize;
let mut pre = vec![vec![0; n]; n];
for i in 0..n {
for j in 0..(n - 1) {
pre[i][preferences[i][j] as usize] = n - j - 1;
}
}The code above reorganizes preferences into pre. We can then query it conveniently with pre[i][j].
Next, carefully observe the unhappy condition in the example and rewrite it as code:
pre[x][u] > pre[x][y] && pre[u][x] > pre[u][v]
This expression is interesting. When it holds, not only is x unhappy, but u is unhappy as well.
Looking further, we can see that this expression is completely determined by x and u. Therefore, among the four variables x,y,u,v, there are four such pairs of combinations.
# let (a, b, c, d) = (0, 0, 0, 0);
# let pre = vec![vec![3]];
# let mut set = std::collections::HashSet::new();
if pre[a][c] > pre[a][b] && pre[c][a] > pre[c][d] {
set.insert(a);
set.insert(c);
}
if pre[b][c] > pre[b][a] && pre[c][b] > pre[c][d] {
set.insert(b);
set.insert(c);
}
if pre[b][d] > pre[b][a] && pre[d][b] > pre[d][c] {
set.insert(b);
set.insert(d);
}
if pre[d][a] > pre[d][c] && pre[a][d] > pre[a][b] {
set.insert(d);
set.insert(a);
}Here, set is a hash set used to avoid duplicates. (x,y,u,v are written as a,b,c,d for convenience.)
Finally, iterate over the hash set and return its size.
Rust Code#
# struct Solution;
impl Solution {
pub fn unhappy_friends(n: i32, preferences: Vec<Vec<i32>>, pairs: Vec<Vec<i32>>) -> i32 {
let n = n as usize;
let mut pre = vec![vec![0; n]; n];
for i in 0..n {
for j in 0..(n - 1) {
pre[i][preferences[i][j] as usize] = n - j - 1;
}
}
// println!("{:?}", pre);
use std::collections::*;
let mut set = HashSet::new();
for i in 0..pairs.len() {
for j in 0..pairs.len() {
let a = pairs[i][0] as usize;
let b = pairs[i][1] as usize;
let c = pairs[j][0] as usize;
let d = pairs[j][1] as usize;
if pre[a][c] > pre[a][b] && pre[c][a] > pre[c][d] {
set.insert(a);
set.insert(c);
}
if pre[b][c] > pre[b][a] && pre[c][b] > pre[c][d] {
set.insert(b);
set.insert(c);
}
if pre[b][d] > pre[b][a] && pre[d][b] > pre[d][c] {
set.insert(b);
set.insert(d);
}
if pre[d][a] > pre[d][c] && pre[a][d] > pre[a][b] {
set.insert(d);
set.insert(a);
}
}
}
set.len() as i32
}
}
