Skip to content

Commit 492e6f7

Browse files
authored
Create 765._Couples_Holding_Hands.md
1 parent af3fdbd commit 492e6f7

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# 765. Couples Holding Hands
2+
3+
**<font color=red>难度: Hard</font>**
4+
5+
## 刷题内容
6+
7+
> 原题连接
8+
9+
* https://leetcode.com/problems/couples-holding-hands/
10+
11+
> 内容描述
12+
13+
```
14+
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.
15+
16+
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).
17+
18+
The couples' initial seating is given by row[i] being the value of the person who is initially sitting in the i-th seat.
19+
20+
Example 1:
21+
22+
Input: row = [0, 2, 1, 3]
23+
Output: 1
24+
Explanation: We only need to swap the second (row[1]) and third (row[2]) person.
25+
Example 2:
26+
27+
Input: row = [3, 2, 0, 1]
28+
Output: 0
29+
Explanation: All couples are already seated side by side.
30+
Note:
31+
32+
len(row) is even and in the range of [4, 60].
33+
row is guaranteed to be a permutation of 0...len(row)-1.
34+
```
35+
36+
## 解题方案
37+
38+
> 思路 1
39+
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
40+
41+
证明过程参考[Java/C++ O(N) solution using cyclic swapping](https://leetcode.com/problems/couples-holding-hands/discuss/113362/JavaC%2B%2B-O(N)-solution-using-cyclic-swapping)
42+
43+
以下所有的group指的都是connected component
44+
45+
并查集的思想,by saying "resolving a group", we mean placing the elements at each index contained in the group to
46+
their expected positions at the end of the swapping process.
47+
48+
先assume一个论点,size为n的group需要n-1次swap来使得所有的元素放在它应该在的index上
49+
50+
- Base case:如果是一个size 为1的group,我们只需要0次swap就可以让所有的元素放在它应该在的index上
51+
- Induction case:如果是一个size 为k+1的group,那么这个group就是```... --> i --> p --> ... --> j --> q --> ....```的形式,
52+
假设i本应该在的位置是j所在的位置,j本应该在的位置是i所在的位置,那么我们将i和j互相换一下,就将这个size为 k+1的group分成了两个disjoint的group。
53+
假设这两个group的size分别为k1和k2,那么我们一直分下去,可以一直分到base case的情况,也就是说size为k1的group需要k1-1次swap,size为k2的grouo
54+
需要k2-1次swap,那么将整个size为k的group全部放到正确的位置上所需要的swap次数就是```1 + (k1-1) + (k2-1)```,也就是```k1+k2-1```
55+
,而其中```k1 + k2 = k```,所以对于Induction case来说也满足这个论点
56+
57+
证毕
58+
59+
那么对于我们的N对couple来说,其实就是N个node,我们可以把作为input的row看成一个大家庭,其中有几个group我们可以通过并查集或者dfs算出来,设为m,
60+
每做一次swap我们就可以增加一个group,最终我们的目的就是形成N个group,即N对couple,所以我们一共需要N-m次swap
61+
62+
并查集,beats 34.83%
63+
64+
```python
65+
class UnionFind(object):
66+
def __init__(self, n): # 初始化uf数组和组数目
67+
self.count = n
68+
self.uf = [i for i in range(n)]
69+
70+
def find(self, x): # 判断节点所属于的组
71+
while x != self.uf[x]:
72+
self.uf[x] = self.uf[self.uf[x]]
73+
x = self.uf[x]
74+
return self.uf[x]
75+
76+
def union(self, x, y): # 连接两个节点
77+
x_root = self.find(x)
78+
y_root = self.find(y)
79+
if x_root == y_root:
80+
return
81+
self.uf[x_root] = y_root
82+
self.count -= 1
83+
84+
class Solution:
85+
def minSwapsCouples(self, row):
86+
"""
87+
:type row: List[int]
88+
:rtype: int
89+
"""
90+
N = len(row) // 2
91+
uf = UnionFind(N)
92+
for i in range(N):
93+
m, n = row[2*i], row[2*i+1]
94+
uf.union(m // 2, n // 2) # 说明这两对couple,即这两个node相互连接
95+
return N - uf.count
96+
```
97+
98+
99+
> 思路 2
100+
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
101+
102+
看完上面的思路,发现直接用贪心就可以,就是直接从头到尾遍历,没配对成功就立马配对,执行相应swap操作
103+
104+
beats 34.83%
105+
106+
107+
```python
108+
class Solution:
109+
def minSwapsCouples(self, row):
110+
"""
111+
:type row: List[int]
112+
:rtype: int
113+
"""
114+
lookup = {} # people: his idx in row
115+
for idx, ppl in enumerate(row):
116+
lookup[ppl] = idx
117+
res = 0
118+
for i in range(0, len(row), 2):
119+
p1 = row[i]
120+
p2 = p1 + 1 if p1 % 2 == 0 else p1 - 1 # Find p1's couple
121+
if row[i+1] != p2: # p1's couple isn't next to p1
122+
res += 1
123+
s = row[i+1] # stranger
124+
lookup[s], lookup[p2] = lookup[p2], i+1 # swap p2 and cur stranger
125+
row[lookup[s]], row[i+1] = s, p2 # couple in right idx, Stranger is gone
126+
return res
127+
```
128+
129+
130+
131+
132+
133+
134+
135+
136+
137+
138+
139+
140+
141+
142+
143+
144+
145+
146+
147+
148+
149+
150+
151+

0 commit comments

Comments
 (0)