Leetcode5650. 执行交换操作后的最小汉明距离
今天分享双周赛的第三题,有关知识点是并查集。说来惭愧,之前刚整理过并查集的相关知识,做了些题目练练手,周赛的时候还是没有往这上面想,总是想着去匹配字符串。下面来整理下这道题目
- 题目
给你两个整数数组 source 和 target ,长度都是 n 。还有一个数组 allowedSwaps ,其中每个 allowedSwaps[i] = [ai, bi] 表示你可以交换数组 source 中下标为 ai 和 bi(下标从 0 开始)的两个元素。注意,你可以按 任意 顺序 多次 交换一对特定下标指向的元素。
相同长度的两个数组 source 和 target 间的 汉明距离 是元素不同的下标数量。形式上,其值等于满足 source[i] != target[i] (下标从 0 开始)的下标 i(0 <= i <= n-1)的数量。
在对数组 source 执行 任意 数量的交换操作后,返回 source 和 target 间的 最小汉明距离 。
示例 1:
输入:source = [1,2,3,4], target = [2,1,4,5], allowedSwaps = [[0,1],[2,3]]
输出:1
解释:source 可以按下述方式转换:
- 交换下标 0 和 1 指向的元素:source = [2,1,3,4]
- 交换下标 2 和 3 指向的元素:source = [2,1,4,3]
source 和 target 间的汉明距离是 1 ,二者有 1 处元素不同,在下标 3 。
示例 2:
输入:source = [1,2,3,4], target = [1,3,2,4], allowedSwaps = []
输出:2
解释:不能对 source 执行交换操作。
source 和 target 间的汉明距离是 2 ,二者有 2 处元素不同,在下标 1 和下标 2 。
示例 3:
输入:source = [5,1,2,4,3], target = [1,5,4,2,3], allowedSwaps = [[0,4],[4,2],[1,3],[1,4]]
输出:0
- 解释
汉明距离可以这样理解:对应位置元素不同则汉明距离加1
根据题意我们可以了解到,如果说0,1之间可以交换,1,3之间可以交换,那么0,3之间也是可以交换的。
因此,我们可以用并查集来维护这个联通块,对于source数组中任意两位置i,j,如果i,j在同一个联通分支里,那么i,j之间是可以互相交换的。不同联通块之间是没有任何联系。
对于任意的联通分支k,由于他们内部的位置可以任意交换,因此他们在source中的顺序并不重要,我们只需要对source数组中每个位置的数进行查询,看他们属于哪个集合并计数。
最后我们在遍历target数组,对每个位置的数,查看对应的集合,看是否存在,记录数量并更新计数
-
遍历allowedSwaps数组中的所有元素,从而构建数组中位置的联通关系
-
然后使用哈希表映射数组
target
中的每个元素和其位置,以便后续查找数组source
中的元素在数组target
中的位置 -
代码
class Solution {
public:
vector<int> p;
int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
int minimumHammingDistance(vector<int>& source, vector<int>& target, vector<vector<int>>& allowedSwaps) {
int n = source.size();
for (int i = 0;i < n; i++) p.push_back(i);
//集合合并,可以交换的元素所在的联通块可以合并
for (auto& t : allowedSwaps) {
p[find(t[0])] = find(t[1]);
}
//把source里每个联通块的所有元素放到每个联通块对应的哈希表里
vector<unordered_multiset<int>> h(n);
//枚举source里的所有元素
for (int i = 0;i < n; i++) {
h[find(i)].insert(source[i]);
}
int res = 0;
for (int i = 0;i < n; i++) {
//target里对应点所在联通块的哈希表
auto &t = h[find(i)];
//如果此哈希表存在target[i],说明这个元素可以交换到
if (t.count(target[i])) {
t.erase(t.find(target[i]));
}else {
res++;
}
}
return res;
}
};