zoukankan      html  css  js  c++  java
  • LeetCode765. 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.

    思路

    本来以为是用dp解题,然而不是,还是好好背题吧。解法有 cyclic swapping,并差集,贪心这三种。

    完整解释:https://leetcode.com/problems/couples-holding-hands/discuss/113362/JavaC++-O(N)-solution-using-cyclic-swapping

    一大串英文解释,看的不是很懂,百度了下,看到一片篇解释得很易懂的博文:

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

    首先是贪心的解法:

    class Solution {
        public int minSwapsCouples(int[] row) {
            int res=0, n=row.length;
            for(int i=0;i<n;i=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)){  // 这里注意要加括号,因为java中恒等运算符的优先级大于位运算
                        row[j]=row[i+1];
                        row[i+1]=(row[i]^1);
                        break;
                    }
                }
            }
            return res;
        }
    }

    接下来是并查集的解法,关于并查集算法的解释可以见这篇博文:https://blog.csdn.net/dm_vincent/article/details/7655764

    LeetCode上的解释:

    Think about each couple as a vertex(顶点) in the graph. So if there are N couples, there are N vertices. Now if in position 2i and 2i +1 there are person from couple u and couple v sitting there, that means that the permutations are going to involve u and v. So we add an edge to connect u and v. The min number of swaps = N - number of connected components. This follows directly from the theory of permutations. Any permutation can be decomposed into a composition of cyclic permutations. If the cyclic permutation involve k elements, we need k -1 swaps. You can think about each swap as reducing the size of the cyclic permutation by 1. So in the end, if the graph has k connected components, we need N - k swaps to reduce it back to N disjoint vertices.

    class Solution {
        private class UF {
            private int[] parents;
            public int count;
            UF(int n) {  // 初始化组号
                parents = new int[n];
                for (int i = 0; i < n; i++) {
                    parents[i] = i;  // i-具体节点的值,parents[i]-节点i所对应的组号,放在这题中i就是couple的编号,数组值就是这个couple应该在的组号
                }
                count = n;
            }
            
            private int find(int i) {
                if (parents[i] == i) {  // 如果couple的编号和组号对应,所在组号正确,直接返回组号
                    return i;
                }
                parents[i] = find(parents[i]);  // 这种情形时发生了标记1的情况,连接后组号被修改过,不会和原来对应
                return parents[i];
            }
            
            public void union(int i, int j) {
                int a = find(i);
                int b = find(j);
                if (a != b) {  // 如果不在一个组,连接之
                    parents[a] = b;  // 将a的组号改成b的,注意原parents数组如果组号是a,那么其数组索引也是a。标记1
                    count--;  
                }
            }
        }
        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];
                int b = row[2*i + 1];
                uf.union(a/2, b/2);
            }
            return N - uf.count;
        }
    }
  • 相关阅读:
    Masonry复杂ScrollView布局
    Masonry scrollview循环布局
    Masonry tableviewCell布局
    Masonry 比例(multipliedBy)
    Masonry自动布局:复合约束
    Masonry整体动画更新约束
    Masonry remake更新约束
    Masonry 动画更新约束
    Masonry基本用法
    Spring Quartz 和 Spring Task使用比较
  • 原文地址:https://www.cnblogs.com/f91og/p/9515418.html
Copyright © 2011-2022 走看看