LeetCode每日一题(765. Couples Holding Hands)

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
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值