1. 程式人生 > 其它 >2021-02-14

2021-02-14

技術標籤:leetcode

2021-02-14 Leetcode每日刷題

題目

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:

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

我的思路
是看了解答的貪心策略才敢寫的。對於每組數字(2i, 2i+1),當第一個數為偶數的時候檢查第二個數是否比它大1,如果不是則搜尋到之後交換一次。當第一個數為奇數的時候檢查第二個數是否比它小1並進行交換。我也不知道這樣為什麼是對的,但是它的答案確實是對的。

class Solution:
    def minSwapsCouples(self, row: List[int
]) -> int: cnt = 0 for i in range(int(len(row)/2)): if row[2*i]%2 == 0: if row[2*i+1] != row[2*i] +1: for j in range(2*i+1,len(row)): if row[j] == row[2*i]+1: row[2*i+1],row[j] = row[j],row[2*i+1] cnt+=1 else: if row[2*i+1] != row[2*i] - 1: for j in range(2*i+1,len(row)): if row[j] == row[2*i]-1: row[2*i+1],row[j] = row[j],row[2*i+1] cnt+=1 return cnt

提交結果
在這裡插入圖片描述
參考思路
關於為什麼貪心解法是正確的:

  • 從圖的角度來講,將N對情侶看做圖中的 N 個節點;對於每對相鄰的位置,如果是第i對與第j對坐在了一起,則在i號節點與j號節點之間連線一條邊,代表需要交換這兩對情侶的位置。

  • 因為這題情侶是2人一對,同一連通分量內,每個點最多連出兩條邊,且必成環(可以用反證法;當連通分量內只有一個點時,說明該情侶坐對了,不需要換位置;只有兩個點時,圖中只有一條邊,直接調換一次即可;在一般情況下,即連通分量內點數大於2時,此時每個點必須連出兩條邊[如果只連一條邊的話,一定屬於第二種只有兩個點的情況;連三條邊不可能,因為情侶是2人]!這一條件當且僅當成環的時候成立,反之會出現某些點只有一條邊或者多餘兩條邊的情況)。

  • 至此,對於每個連通分量,由於其一定成環,所以我們直接沿著環的方向依次交換(邊數-1)次即可使得該連通分量內情侶牽手,也就是貪心交換。

一個簡化版的程式碼:

class Solution(object):
    def minSwapsCouples(self, row):
        """
        :type row: List[int]
        :rtype: int
        """
        N = len(row)
        res = 0
        for i in range(0, N - 1, 2):
            if row[i] == row[i + 1] ^ 1:
                continue
            for j in range(i + 1, N):
                if row[i] == row[j] ^ 1:
                    row[i + 1], row[j] = row[j], row[i + 1]
            res += 1
        return res

這裡有個小技巧合並奇數偶數兩種情況:

求數字 x 的物件時用到了一個技巧,x 的物件是x ^ 1。解釋如下:

  • 當 x 是偶數,則其二進位制的末尾是 0,所以 x ^ 1 將其二進位制的末尾改成 1,於是得到了x的物件 x + 1。 當 x
  • 是奇數,則其二進位制的末尾是 1,所以 x ^ 1 將其二進位制的末尾改成 0,於是得到了x的物件 x - 1。

情人節算這個好心累。祝天下有情人終成眷屬。
正好一週了,從明天開始加大力度多刷一道簡單題。