Description
You are given two integer arrays, source and target, both of length n. You are also given an array allowedSwaps where each allowedSwaps[i] = [ai, bi] indicates that you are allowed to swap the elements at index ai and index bi (0-indexed) of array source. Note that you can swap elements at a specific pair of indices multiple times and in any order.
The Hamming distance of two arrays of the same length, source and target, is the number of positions where the elements are different. Formally, it is the number of indices i for 0 <= i <= n-1 where source[i] != target[i] (0-indexed).
Return the minimum Hamming distance of source and target after performing any amount of swap operations on array source.
Example 1:
Input: source = [1,2,3,4], target = [2,1,4,5], allowedSwaps = [[0,1],[2,3]]
Output: 1
Explanation: source can be transformed the following way:
- Swap indices 0 and 1: source = [2,1,3,4]
- Swap indices 2 and 3: source = [2,1,4,3]
The Hamming distance of source and target is 1 as they differ in 1 position: index 3.
Example 2:
Input: source = [1,2,3,4], target = [1,3,2,4], allowedSwaps = []
Output: 2
Explanation: There are no allowed swaps.
The Hamming distance of source and target is 2 as they differ in 2 positions: index 1 and index 2.
Example 3:
Input: source = [5,1,2,4,3], target = [1,5,4,2,3], allowedSwaps = [[0,4],[4,2],[1,3],[1,4]]
Output: 0
Constraints:
- n == source.length == target.length
- 1 <= n <= 105
- 1 <= source[i], target[i] <= 105
- 0 <= allowedSwaps.length <= 105
- allowedSwaps[i].length == 2
- 0 <= ai, bi <= n - 1
- ai != bi
分析
题目的意思是:求source数组的元素经过交换以后与target的最小hamming距离。这里的hammming距离相同位置不同元素的个数。解法我参考了别人的,我也写不出来哈。
- 首先构造UnionFind,把allowedSwaps中的元素求并集合,即分成连通子图。
- 字典m表示的是连通子图的集合,key就是UnionFind树的根节点,这样就把连通子图放进字典里面了。
- 最后就是求连通子图对应的source和target元素的交集的个数cnt,差集就是len(A)-cnt了,更新res,res就是最终的结果了
解法挺巧妙的,需要先把allowedSwaps求出并查集,然后代入到source和target,得到在allowedSwaps下的source和target各自的索引集合,然后根据索引集合求出差集,因为只有不相同的元素才能贡献hamming距离啦。我学习一下,哈哈哈
代码
class UnionFind:
def __init__(self,n):
self.root=list(range(n))
def find(self,x):
if(x!=self.root[x]):
self.root[x]=self.find(self.root[x])
return self.root[x]
def union(self,x,y):
self.root[self.find(x)]=self.find(y)
class Solution:
def minimumHammingDistance(self, source: List[int], target: List[int], allowedSwaps: List[List[int]]) -> int:
n=len(source)
uf=UnionFind(n)
for x,y in allowedSwaps:
uf.union(x,y)
m=defaultdict(list)
for i in range(n):
m[uf.find(i)].append(i)
res=0
for item in m:
indexes=m[item]
A=[]
B=[]
for idx in indexes:
A.append(source[idx])
B.append(target[idx])
cnt=0
c1=Counter(A)
c2=Counter(B)
for k1 in c1:
if(k1 in c2):
cnt+=min(c1[k1],c2[k1])
res+=len(A)-cnt
return res