返回介绍

solution / 1700-1799 / 1722.Minimize Hamming Distance After Swap Operations / README_EN

发布于 2024-06-17 01:03:15 字数 8116 浏览 0 评论 0 收藏 0

1722. Minimize Hamming Distance After Swap Operations

中文文档

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

Solutions

Solution 1: Union-Find + Hash Table

We can consider each index as a node, and the element corresponding to each index as the value of the node. Then each element [a_i, b_i] in the given allowedSwaps represents an edge between index a_i and b_i. Therefore, we can use a union-find set to maintain these connected components.

After obtaining each connected component, we use a two-dimensional hash table $cnt$ to count the number of occurrences of each element in each connected component. Finally, for each element in the array target, if its occurrence count in the corresponding connected component is greater than 0, we decrease its count by 1, otherwise, we increase the answer by 1.

The time complexity is $O(n \times \log n)$ or $O(n \times \alpha(n))$, and the space complexity is $O(n)$. Here, $n$ is the length of the array, and $\alpha$ is the inverse Ackermann function.

class Solution:
  def minimumHammingDistance(
    self, source: List[int], target: List[int], allowedSwaps: List[List[int]]
  ) -> int:
    def find(x: int) -> int:
      if p[x] != x:
        p[x] = find(p[x])
      return p[x]

    n = len(source)
    p = list(range(n))
    for a, b in allowedSwaps:
      p[find(a)] = find(b)
    cnt = defaultdict(Counter)
    for i, x in enumerate(source):
      j = find(i)
      cnt[j][x] += 1
    ans = 0
    for i, x in enumerate(target):
      j = find(i)
      cnt[j][x] -= 1
      ans += cnt[j][x] < 0
    return ans
class Solution {
  private int[] p;

  public int minimumHammingDistance(int[] source, int[] target, int[][] allowedSwaps) {
    int n = source.length;
    p = new int[n];
    for (int i = 0; i < n; i++) {
      p[i] = i;
    }
    for (int[] a : allowedSwaps) {
      p[find(a[0])] = find(a[1]);
    }
    Map<Integer, Map<Integer, Integer>> cnt = new HashMap<>();
    for (int i = 0; i < n; ++i) {
      int j = find(i);
      cnt.computeIfAbsent(j, k -> new HashMap<>()).merge(source[i], 1, Integer::sum);
    }
    int ans = 0;
    for (int i = 0; i < n; ++i) {
      int j = find(i);
      Map<Integer, Integer> t = cnt.get(j);
      if (t.merge(target[i], -1, Integer::sum) < 0) {
        ++ans;
      }
    }
    return ans;
  }

  private int find(int x) {
    if (p[x] != x) {
      p[x] = find(p[x]);
    }
    return p[x];
  }
}
class Solution {
public:
  int minimumHammingDistance(vector<int>& source, vector<int>& target, vector<vector<int>>& allowedSwaps) {
    int n = source.size();
    vector<int> p(n);
    iota(p.begin(), p.end(), 0);
    function<int(int)> find = [&](int x) {
      return x == p[x] ? x : p[x] = find(p[x]);
    };
    for (auto& a : allowedSwaps) {
      p[find(a[0])] = find(a[1]);
    }
    unordered_map<int, unordered_map<int, int>> cnt;
    for (int i = 0; i < n; ++i) {
      ++cnt[find(i)][source[i]];
    }
    int ans = 0;
    for (int i = 0; i < n; ++i) {
      if (--cnt[find(i)][target[i]] < 0) {
        ++ans;
      }
    }
    return ans;
  }
};
func minimumHammingDistance(source []int, target []int, allowedSwaps [][]int) (ans int) {
  n := len(source)
  p := make([]int, n)
  for i := range p {
    p[i] = i
  }
  var find func(int) int
  find = func(x int) int {
    if p[x] != x {
      p[x] = find(p[x])
    }
    return p[x]
  }
  for _, a := range allowedSwaps {
    p[find(a[0])] = find(a[1])
  }
  cnt := map[int]map[int]int{}
  for i, x := range source {
    j := find(i)
    if cnt[j] == nil {
      cnt[j] = map[int]int{}
    }
    cnt[j][x]++
  }
  for i, x := range target {
    j := find(i)
    cnt[j][x]--
    if cnt[j][x] < 0 {
      ans++
    }
  }
  return
}
function minimumHammingDistance(
  source: number[],
  target: number[],
  allowedSwaps: number[][],
): number {
  const n = source.length;
  const p: number[] = Array.from({ length: n }, (_, i) => i);
  const find = (x: number): number => {
    if (p[x] !== x) {
      p[x] = find(p[x]);
    }
    return p[x];
  };
  for (const [a, b] of allowedSwaps) {
    p[find(a)] = find(b);
  }
  const cnt: Map<number, Map<number, number>> = new Map();
  for (let i = 0; i < n; ++i) {
    const j = find(i);
    if (!cnt.has(j)) {
      cnt.set(j, new Map());
    }
    const m = cnt.get(j)!;
    m.set(source[i], (m.get(source[i]) ?? 0) + 1);
  }
  let ans = 0;
  for (let i = 0; i < n; ++i) {
    const j = find(i);
    const m = cnt.get(j)!;
    m.set(target[i], (m.get(target[i]) ?? 0) - 1);
    if (m.get(target[i])! < 0) {
      ++ans;
    }
  }
  return ans;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文