• 765. Couples Holding Hands


    问题:

    给定一个座位排表row,

    2n 和 2n+1 (n:0,1,2...) 表示一对情侣。

    把所有人排放在上述座位排表中。求,要使每一对情侣都坐在一起,要交换多少次座位。

    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:
    len(row) is even and in the range of [4, 60].
    row is guaranteed to be a permutation of 0...len(row)-1.
    

      

    解法:并查集(Disjoint Set)

    首先将一对情侣的两个人组成连通图。共形成 row.size/2 个连通图。

    然后,从座位排表中,两两取出,应该坐在一起的两个位置。

    将这两个位置上,当前坐的人连接起来merge。

    最终形成 X 个连通图。

    对每个连通图,代表:应该内部交换位置,使得情侣坐在一起。

    ★每交换一次,能够促成一对情侣相邻坐好,

    这里若进行一次解偶,独立这一对情侣的连通图。

    依此类推操作后,最终若形成 N 个连通图(即N对情侣),

    其中,共进行解偶了,N-1 次(一个连通图 变成 N个连通图),促成 N-1 对情侣相邻(余下最后一对自然相邻)

    由于★,也就是,共交换座位了 N-1 次。

    那么,所有的连通图,共交换  row.size/2 - X 次。

    代码参考:

     1 class Solution {
     2 public:
     3     int minSwapsCouples(vector<int>& row) {
     4         DisjointSet DS(row.size());
     5         for(int i=1; i<row.size(); i+=2) {
     6             DS.merge(i, i-1);
     7         }
     8         for(int i=1; i<row.size(); i+=2) {
     9             DS.merge(row[i], row[i-1]);
    10         }
    11         return row.size() / 2 - DS.getGroupCount();
    12     }
    13 };

    并查集类,代码参考:

     1 class DisjointSet {
     2 public:
     3     DisjointSet(int n):root(n,0), rank(n,0) {
     4         for(int i=0; i<n; i++) {
     5             root[i]=i;
     6         }
     7     }
     8     int find(int i) {
     9         if(root[i]!=i) {
    10             root[i] = find(root[i]);
    11         }
    12         return root[i];
    13     }
    14     bool merge(int x, int y) {
    15         int x_root=find(x);
    16         int y_root=find(y);
    17         if(x_root==y_root) return false;
    18         if(rank[x_root] > rank[y_root]) {
    19             root[y_root] = x_root;
    20         } else if(rank[y_root] > rank[x_root]) {
    21             root[x_root] = y_root;
    22         } else {
    23             root[y_root] = x_root;
    24             rank[x_root]++;
    25         }
    26         return true;
    27     }
    28     int getGroupCount() {
    29         int res=0;
    30         for(int i=0; i<root.size(); i++) {
    31             if(root[i] == i) res++;
    32         }
    33         return res;
    34     }
    35 private:
    36     vector<int> root;
    37     vector<int> rank;
    38 };
  • 相关阅读:
    python 类继承演示范例的代码
    C#监控指定目录的文件变化的代码
    如何开启红米手机4X的ROOT超级权限
    C# 发送电子邮件源码片段
    android中使用afinal一行源码显示网络图片
    (详细)华为畅享7 SLA-AL00的usb调试模式在哪里打开的流程
    C#自定义FTP访问类的代码
    C#的String.Split 分割字符串用法详解的代码
    红米Note 5A完美卡刷开发版获得ROOT超级权限的方法
    C# 类如何声明索引器以提供对类的类似数组的访问的代码
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/13469862.html
Copyright © 2020-2023  润新知