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;
}
};