1. 程式人生 > 實用技巧 >765. Couples Holding Hands

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