There are n couples sitting in 2n seats arranged in a row and want to hold hands.
The people and seats are represented by an integer array row where row[i] is the ID of the person sitting in the ith seat. The couples are numbered in order, the first couple being (0, 1), the second couple being (2, 3), and so on with the last couple being (2n - 2, 2n - 1).
Return the minimum number of swaps so that every couple is sitting side by side. A swap consists of choosing any two people, then they stand up and switch seats.
Example 1:
Input: row = [0,2,1,3]
Output: 1
Explanation: We only need to swap the second (row[1]) and third (row[2]) person.
Example 2:
Input: row = [3,2,0,1]
Output: 0
Explanation: All couples are already seated side by side.
Constraints:
- 2n == row.length
- 2 <= n <= 30
- n is even.
- 0 <= row[i] < 2n
- All the elements of row are unique.
我们把 2 把椅子看做是一个 node, 如果 node_i 与 node_j 中的情侣有换位置的需求, 那我们认为 node_i 与 node_j 之间有 1 条 edge, 这样我们就可以得到一个 graph, 这里的重点是, 只要有换位置的需求,那这些需要换位置的 nodes 和与其相关的 edges 一定会组成 1 个或多个环, 因为一个 node 最多有 2 条 edge, 所以任何一个 node 都不可能同时处于 2 个环中。这样, 我们就可以从任意一个 node 入手开始遍历, 最后我们一定会回到开始的 node, 这样一个环路的 edge 的数量是组成环路的 node 数量-1, 这也是我们实际需要执行换座位的次数。我们遍历完所有的环,最后将每个环的 edge 的数量加起来就是我们所要的答案
use std::collections::{HashMap, HashSet};
impl Solution {
fn dfs(seats: &Vec<(i32, i32)>, positions: &HashMap<i32, usize>, curr: i32, visited: &mut HashSet<usize>) -> i32 {
let couple = if curr % 2 == 0 { curr + 1 } else { curr - 1 };
let pos = *positions.get(&couple).unwrap();
if visited.contains(&pos) {
return 0;
}
visited.insert(pos);
if couple == seats[pos].0 {
return 1 + Solution::dfs(seats, positions, seats[pos].1, visited);
}
1 + Solution::dfs(seats, positions, seats[pos].0, visited)
}
pub fn min_swaps_couples(row: Vec<i32>) -> i32 {
let seats: Vec<(i32, i32)> = row.windows(2).step_by(2).map(|w| (w[0], w[1])).collect();
let positions = seats.iter().enumerate().fold(HashMap::new(), |mut m, (i, (v1, v2))| {
m.insert(*v1, i);
m.insert(*v2, i);
m
});
let mut ans = 0;
let mut visited = HashSet::new();
for (i, &(left, _)) in seats.iter().enumerate() {
if visited.contains(&i) {
continue;
}
visited.insert(i);
ans += Solution::dfs(&seats, &positions, left, &mut visited);
}
ans
}
}