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

[LeetCode] 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. Aswapconsists of choosinganytwo people, then they stand up and switch seats.

The people and seats are represented by an integer from0to2N-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 byrow[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. rowis guaranteed to be a permutation of0...len(row)-1.

情侶牽手。

題意是給偶數個人,以陣列表示。他們的下標是從0到2N - 1。其中(2N - 2, 2N - 1)是情侶。現在請你做swap操作,請問至少需要swap多少次,可以讓所有情侶牽手。

這個題有兩種思路,一種是貪心,一種是並查集union find。我這裡先給出貪心的思路。

這個題貪心的做法跟桶排序類似,還是試著將每個座標上放應該放的數字。過一下第一個例子,[0, 2, 1, 3]。第一個數字是0,那麼第二個數字的判斷就是看他是否是第一個數字0的配偶。判斷配偶的方式是看當前這個nums[i + 1]是不是等於nums[i] ^ 1。這一點不容易想到。因為配偶的座位排序要求不是非常嚴格,比如0和1,既可以01這樣坐,也可以10這樣坐。但是位運算的這個特點就可以無視0和1的順序,來判斷兩個相鄰的數字是否互為配偶。如果想不到這個位運算的辦法,那麼就只能通過先判斷當前index上數字的奇偶性來判斷index + 1那個位置上的數字是否是配偶。貪心的做法為什麼對呢?我這裡引用一個discussion給的例子,並且稍加解釋。

The proof is easy. Consider a simple example: 7 1 4 6 2 3 0 5. At first step we have two choice to match the first couple: swap 7 with 0, or swap 1 with 6. Then we get 0 1 4 6 2 3 7 5 or 7 6 4 1 2 3 0 5. Pay attention that the first couple doesn't count any more. For the later part it is composed of 4 X 2 3 Y 5 (X=6 Y=7 or X=1 Y=0). Since different couples are unrelated, we don't care X Y is 6 7 pair or 0 1 pair. They are equivalent! Thus it means our choice doesn't count.
Therefore, just follow the distinction and you will get it right!

首先,input是[7 1 4 6 2 3 0 5]。然後第一次swap可以swap7和0,或者swap1和6。第一次swap完了之後,陣列長這樣,

4 X 2 3 Y 5 (X=6 Y=7 or X=1 Y=0)

後面的swap只跟XY有關,跟已經被swap好的第一組數字無關了。所以也就無所謂先swap哪些數字了。

時間O(n^2)

空間O(1)

Java實現

 1 class Solution {
 2     public int minSwapsCouples(int[] row) {
 3         int res = 0;
 4         for (int i = 0; i < row.length; i += 2) {
 5             if (row[i + 1] == (row[i] ^ 1)) {
 6                 continue;
 7             }
 8             res++;
 9             for (int j = i + 1; j < row.length; j++) {
10                 if (row[j] == (row[i] ^ 1)) {
11                     row[j] = row[i + 1];
12                     row[i + 1] = row[i] ^ 1;
13                     break;
14                 }
15             }
16         }
17         return res;
18     }
19 }

LeetCode 題目總結