Skip to content

Commit 036f2bf

Browse files
committedJun 14, 2023
feat: add solutions to lc problem: No.0765
No.0765.Couples Holding Hands
1 parent 23496d5 commit 036f2bf

File tree

8 files changed

+337
-235
lines changed

8 files changed

+337
-235
lines changed
 

‎solution/0700-0799/0765.Couples Holding Hands/README.md

+101-101
Original file line numberDiff line numberDiff line change
@@ -46,73 +46,17 @@
4646

4747
<!-- 这里可写通用的实现逻辑 -->
4848

49-
坐错位置的情况与最少需要交换次数:
49+
**方法一:并查集**
5050

51-
- 1 对情侣、2 个座位,不需要交换。
52-
- 2 对情侣、4 个座位,交换 1 次。
53-
- 3 对情侣、6 个座位。首先交换 1 次使得其中 1 对情侣坐在一起,剩下 2 对情侣、4 个座位。即需要交换 2 次。
51+
我们可以给每一对情侣编号,编号 $0$ 和 $1$ 的人对应情侣 $0$,编号 $2$ 和 $3$ 的人对应情侣 $1$...即编号为 $row[i]$ 对应的情侣编号为 $\lfloor \frac{row[i]}{2} \rfloor$。
5452

55-
以此类推,得到 `f(n)=n-1`。即:n 对情侣相互坐错位置,最少需要交换 `n-1`
53+
如果有 $k$ 对情侣相互之间坐错了位置,也即是说,有 $k$ 对情侣处于一个置换环中,那么他们之间需要经过 $k-1$ 次交换才能都坐到正确的位置上
5654

57-
把相互坐错位置的情侣放在一组(同个集合),组内有 n 对情侣就需要 `n-1` 次交换。将 n 对情侣分为 K 组:N1,N2...Nk,有 N1+N2+...+Nk=n。需要交换的次数分别为:N1-1、N2-1、...、Nk-1,则总的最少交换次数为 N1-1+N2-1+...+Nk-1=N1+N2+...+Nk-k=n-k。问题转换为:n 对情侣,根据相互坐错位置的条件分组,共有多少个分组。并查集实现
55+
为什么?不妨这样考虑,我们先调整一对情侣的位置,使其坐到正确的位置上,那么问题就从 $k$ 对情侣的问题,转换成了 $k-1$ 对情侣的问题。依此类推,最终 $k=1$ 时,交换次数为 $0$。所以,如果 $k$ 对情侣相互之间坐错了位置,那么需要 $k-1$ 次交换
5856

59-
模板 1——朴素并查集:
57+
因此,我们只需要遍历一遍数组,利用并查集找出有多少个置换环,假设有 $x$ 个,每个环的大小(情侣的对数)为 $y_1, y_2, \cdots, y_x$,那么需要交换的次数为 $y_1-1 + y_2-1 + \cdots + y_x-1 = y_1 + y_2 + \cdots + y_x - x = n - x$。
6058

61-
```python
62-
# 初始化,p存储每个点的父节点
63-
p = list(range(n))
64-
65-
# 返回x的祖宗节点
66-
def find(x):
67-
if p[x] != x:
68-
# 路径压缩
69-
p[x] = find(p[x])
70-
return p[x]
71-
72-
73-
# 合并a和b所在的两个集合
74-
p[find(a)] = find(b)
75-
```
76-
77-
模板 2——维护 size 的并查集:
78-
79-
```python
80-
# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
81-
p = list(range(n))
82-
size = [1] * n
83-
84-
# 返回x的祖宗节点
85-
def find(x):
86-
if p[x] != x:
87-
# 路径压缩
88-
p[x] = find(p[x])
89-
return p[x]
90-
91-
# 合并a和b所在的两个集合
92-
if find(a) != find(b):
93-
size[find(b)] += size[find(a)]
94-
p[find(a)] = find(b)
95-
```
96-
97-
模板 3——维护到祖宗节点距离的并查集:
98-
99-
```python
100-
# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离
101-
p = list(range(n))
102-
d = [0] * n
103-
104-
# 返回x的祖宗节点
105-
def find(x):
106-
if p[x] != x:
107-
t = find(p[x])
108-
d[x] += d[p[x]]
109-
p[x] = t
110-
return p[x]
111-
112-
# 合并a和b所在的两个集合
113-
p[find(a)] = find(b)
114-
d[find(a)] = distance
115-
```
59+
时间复杂度 $O(n \times \alpha(n))$,空间复杂度 $O(n)$。其中 $\alpha(n)$ 为阿克曼函数的反函数,可以认为是一个很小的常数。
11660

11761
<!-- tabs:start -->
11862

@@ -123,7 +67,7 @@ d[find(a)] = distance
12367
```python
12468
class Solution:
12569
def minSwapsCouples(self, row: List[int]) -> int:
126-
def find(x):
70+
def find(x: int) -> int:
12771
if p[x] != x:
12872
p[x] = find(p[x])
12973
return p[x]
@@ -150,17 +94,17 @@ class Solution {
15094
for (int i = 0; i < n; ++i) {
15195
p[i] = i;
15296
}
153-
for (int i = 0; i < row.length; i += 2) {
97+
for (int i = 0; i < n << 1; i += 2) {
15498
int a = row[i] >> 1, b = row[i + 1] >> 1;
15599
p[find(a)] = find(b);
156100
}
157-
int cnt = 0;
101+
int ans = n;
158102
for (int i = 0; i < n; ++i) {
159103
if (i == find(i)) {
160-
++cnt;
104+
--ans;
161105
}
162106
}
163-
return n - cnt;
107+
return ans;
164108
}
165109

166110
private int find(int x) {
@@ -177,64 +121,120 @@ class Solution {
177121
```cpp
178122
class Solution {
179123
public:
180-
vector<int> p;
181-
182124
int minSwapsCouples(vector<int>& row) {
183-
int n = row.size() >> 1;
184-
p.resize(n);
185-
for (int i = 0; i < n; ++i) {
186-
p[i] = i;
187-
}
188-
for (int i = 0; i < row.size(); i += 2) {
125+
int n = row.size() / 2;
126+
int p[n];
127+
iota(p, p + n, 0);
128+
function<int(int)> find = [&](int x) -> int {
129+
if (p[x] != x) {
130+
p[x] = find(p[x]);
131+
}
132+
return p[x];
133+
};
134+
for (int i = 0; i < n << 1; i += 2) {
189135
int a = row[i] >> 1, b = row[i + 1] >> 1;
190136
p[find(a)] = find(b);
191137
}
192-
int cnt = 0;
138+
int ans = n;
193139
for (int i = 0; i < n; ++i) {
194-
if (i == find(i))
195-
++cnt;
140+
ans -= i == find(i);
196141
}
197-
return n - cnt;
198-
}
199-
200-
int find(int x) {
201-
if (p[x] != x) {
202-
p[x] = find(p[x]);
203-
}
204-
return p[x];
142+
return ans;
205143
}
206144
};
207145
```
208146
209147
### **Go**
210148
211149
```go
212-
var p []int
213-
214150
func minSwapsCouples(row []int) int {
215151
n := len(row) >> 1
216-
p = make([]int, n)
217-
for i := 0; i < n; i++ {
152+
p := make([]int, n)
153+
for i := range p {
218154
p[i] = i
219155
}
220-
for i := 0; i < len(row); i += 2 {
156+
var find func(int) int
157+
find = func(x int) int {
158+
if p[x] != x {
159+
p[x] = find(p[x])
160+
}
161+
return p[x]
162+
}
163+
for i := 0; i < n<<1; i += 2 {
221164
a, b := row[i]>>1, row[i+1]>>1
222165
p[find(a)] = find(b)
223166
}
224-
cnt := 0
225-
for i := 0; i < n; i++ {
226-
if i == find(i) {
227-
cnt++
167+
ans := n
168+
for i := range p {
169+
if find(i) == i {
170+
ans--
228171
}
229172
}
230-
return n - cnt
173+
return ans
231174
}
175+
```
232176

233-
func find(x int) int {
234-
if p[x] != x {
235-
p[x] = find(p[x])
236-
}
237-
return p[x]
177+
### **TypeScript**
178+
179+
```ts
180+
function minSwapsCouples(row: number[]): number {
181+
const n = row.length >> 1;
182+
const p: number[] = Array(n)
183+
.fill(0)
184+
.map((_, i) => i);
185+
const find = (x: number): number => {
186+
if (p[x] !== x) {
187+
p[x] = find(p[x]);
188+
}
189+
return p[x];
190+
};
191+
for (let i = 0; i < n << 1; i += 2) {
192+
const a = row[i] >> 1;
193+
const b = row[i + 1] >> 1;
194+
p[find(a)] = find(b);
195+
}
196+
let ans = n;
197+
for (let i = 0; i < n; ++i) {
198+
if (i === find(i)) {
199+
--ans;
200+
}
201+
}
202+
return ans;
203+
}
204+
```
205+
206+
### **C#**
207+
208+
```cs
209+
public class Solution {
210+
private int[] p;
211+
212+
public int MinSwapsCouples(int[] row) {
213+
int n = row.Length >> 1;
214+
p = new int[n];
215+
for (int i = 0; i < n; ++i) {
216+
p[i] = i;
217+
}
218+
for (int i = 0; i < n << 1; i += 2) {
219+
int a = row[i] >> 1;
220+
int b = row[i + 1] >> 1;
221+
p[find(a)] = find(b);
222+
}
223+
int ans = n;
224+
for (int i = 0; i < n; ++i) {
225+
if (p[i] == i) {
226+
--ans;
227+
}
228+
}
229+
return ans;
230+
}
231+
232+
private int find(int x) {
233+
if (p[x] != x) {
234+
p[x] = find(p[x]);
235+
}
236+
return p[x];
237+
}
238238
}
239239
```
240240

0 commit comments

Comments
 (0)