• 765. Couples Holding Hands


    N couples sit in 2N seats arranged in a row and want to hold hands. We want to know 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.

    The people and seats are represented by an integer from 0 to 2N-1, 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).

    The couples' initial seating is given by row[i] being the value of the person who is initially sitting in the i-th seat.

    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.
    

    Note:

    1. len(row) is even and in the range of [4, 60].
    2. row is guaranteed to be a permutation of 0...len(row)-1.

    https://leetcode.com/problems/couples-holding-hands/discuss/117520/Java-union-find-easy-to-understand-5-ms

    class Solution {
        class UF {
            int[] parent;
            int count;
            public UF(int n) {
                parent = new int[n];
                count = n;
                for(int i = 0; i < n; i++) parent[i] = i;
            }
            
            public int find(int x) {
                if(x != parent[x]) x = find(parent[x]);
                return x;
            }
            public void union(int a, int b) {
                int ap = find(a);
                int bp = find(b);
                if(ap != bp) {
                    count--;
                    parent[ap] = bp;
                }
            }
        }
        public int minSwapsCouples(int[] row) {
            int n = row.length / 2;
            UF uf = new UF(n);
            for(int i = 0; i < n; i++) {
                int a = row[2 * i] / 2;
                int b = row[2 * i + 1] / 2;
                uf.union(a, b);
            }
            return n - uf.count;
        }
    }

    居然是个union find!

    理解一下:每一对couple在union里面代表的数相同,都是nums[2*i] / 2, nums[2 * i + 1] / 2, 比如【0,1,2,3,4,5】对应的就是【0,0,1,1,2,2】

    然后我们初始化之后,设置一个count参数,代表不需要换位置的couple数,初始是2n/2 = n。

    然后对每一对潜在的couple(我们先假设他们是),比如【0,3,2,1】,我们对0,3来说,在union他就是0,1,然后他们parent不相等,说明需要交换一次,交换后把0指向1或者1指向0都可以,然后count--。

    这样我们到了2,1,在union中他是1,0.这时因为他们的parent已经相同,所以我们就不用union了,count也不用--。所以最后答案就是n - count = 2 - 1 = 1交换一次。

    同理对【0,5,1,3,2,4】,表示为【0,2,0,1,1,2】。

    0先指向2,count--,

    然后2指向1,count--,

    最后到1,2的时候他们parent又相同了!所以答案是n - count = 3 - 1 = 2,交换两次。

    class Solution {
        public int minSwapsCouples(int[] row) {
            int res = 0, n = row.length;
            for (int i = 0; i < n; i += 2) {
                if (row[i + 1] == (row[i] ^ 1)) continue;
                ++res;
                for (int j = i + 1; j < n; ++j) {
                    if (row[j] == (row[i] ^ 1)) {
                        row[j] = row[i + 1];
                        row[i + 1] = row[i] ^ 1;
                        break;
                    }
                }
            }
            return res;
        }
    }

    这是greedy的做法,对每一对不成双成对的,我们直接交换,把它的对应数接过来。

     https://www.cnblogs.com/grandyang/p/8716597.html

  • 相关阅读:
    博弈论进阶之树的删边游戏与无向图的删边游戏
    博弈论进阶之Every-SG
    HDU 3595 GG and MM(Every-SG)
    博弈论入门之斐波那契博弈
    博弈论入门之威佐夫博弈
    博弈论进阶之Multi-SG
    博弈论进阶之Anti-SG游戏与SJ定理
    博弈论进阶之SG函数
    【每天一个Linux命令】12. Linux中which命令的用法
    《数学之美》之悟——学懂数学为何如此重要?
  • 原文地址:https://www.cnblogs.com/wentiliangkaihua/p/13757655.html
Copyright © 2020-2023  润新知