AcWing 1224. 交换瓶子
思路:
方法1:图的方式找环,数组长度为n
,找环的个数cnt
,最终结果为n - cnt
方法2:连通块的方式找环
765. 情侣牵手
n 对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手。
人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的 ID。情侣们按顺序编号,第一对是 (0, 1),第二对是 (2, 3),以此类推,最后一对是 (2n-2, 2n-1)。
返回 最少交换座位的次数,以便每对情侣可以并肩坐在一起。 每次交换可选择任意两人,让他们站起来交换座位。
示例 1:
输入: row = [0,2,1,3] 输出: 1 解释: 只需要交换row[1]和row[2]的位置即可。
示例 2:
输入: row = [3,2,0,1] 输出: 0 解释: 无需交换座位,所有的情侣都已经可以手牵手了。
提示:
- 2n == row.length
- 2 <= n <= 30
- n 是偶数
- 0 <= row[i] < 2n
- row 中所有元素均无重复
思路:
方法1:
转换成类似上一题的思路,选定偶数下标上的数作为基准,如果有两个偶数下标上的数本身能凑成一对,通过置换找到一个新数即可。通过映射将其转换为与上一题完全一致的模式然后找环
class Solution {
public int minSwapsCouples(int[] row) {
int n = row.length, m = n / 2;
boolean[] st = new boolean[m];
int[] used = new int[m];
Arrays.fill(used, -1);
int[] a = new int[m], b = new int[m];
int[] map = new int[m];
int cnt = 0;
for (int i = 0; i < n; i++)
row[i] /= 2;
for (int i = 0, j = 0; i < n; j++, i += 2) {
while (used[row[i]] != -1) {
cnt++;
swap(row, i, used[row[i]] + 1);
}
used[row[i]] = i;
a[j] = row[i];
map[row[i]] = j;
}
for (int i = 1, j = 0; i < n; i += 2, j++) {
b[j] = map[row[i]];
}
for (int i = 0; i < m; i++) {
if (st[i] || b[i] == i) continue;
int x = b[i];
while (x != i) {
st[x] = true;
x = b[x];
cnt++;
}
}
return cnt;
}
void swap(int[] a, int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
方法2:<br />并查集找连通块,如何merge?<br />首先对所有元素整除2,使得本应在同一座位上的两个元素大小一致<br />对于一个座位上的两个人,合并他们即可<br />最终结果就是总座位数 - 连通块数量