📌  相关文章
📜  查找数组中包含 k 个不同元素所需的最小更改(1)

📅  最后修改于: 2023-12-03 15:10:44.881000             🧑  作者: Mango

查找数组中包含 k 个不同元素所需的最小更改

什么是“最小更改”?

“最小更改”指的是对数组进行修改,使得数组中包含 k 个不同的元素,且修改次数最少。

解决方法
方法一:哈希表

思路:

  1. 遍历数组,将元素存入哈希表中;
  2. 统计哈希表中不同元素的个数;
  3. 若哈希表中不同元素的个数小于等于 k,则不需要修改数组;
  4. 若哈希表中不同元素的个数大于 k,则需要进行修改操作;
  5. 对哈希表中出现次数最少的元素进行修改,使其变为数组中不存在的元素,直到哈希表中不同元素的个数等于 k 为止。

代码片段:

def minChanges(nums: List[int], k: int) -> int:
    n = len(nums)
    max_val = 2 ** 10
    f = [float("inf")] * max_val
    f[0] = 0
  
    for i in range(k):
        cnt = Counter(nums[i::k])
        t2min = min(f)
        g = [t2min] * max_val
        for x, cx in cnt.items():
            for j in range(max_val):
                g[x ^ j] = min(g[x ^ j], f[j] - cx)
        f = [val + t2 for val, t2 in zip(g, [cnt[x] for x in range(max_val)])]
        # print(f, g)
  
    return f[0]
方法二:滑动窗口 + 双指针

思路:

  1. 定义左右指针,使得子数组 nums[left:right] 中不同元素的个数为 k;
  2. 统计 nums[left:right] 中每个元素出现次数的最小值 min_val;
  3. 左指针右移,右指针不动,直到 nums[left:right] 中不同元素的个数小于 k;
  4. 右指针右移,左指针不动,直到 nums[left:right] 中不同元素的个数等于 k,统计 nums[left:right] 中每个元素出现次数的最小值 min_val;
  5. 对所有可能的 nums[left:right] 进行统计,找出最小的 min_val。

代码片段:

def minChanges(nums: List[int], k: int) -> int:
    n = len(nums)
    max_val = 2 ** 10
    f = [float("inf")] * max_val
    f[0] = 0
  
    for i in range(k):
        cnt = Counter(nums[i::k])
        t2min = min(f)
        g = [t2min] * max_val
        for x, cx in cnt.items():
            for j in range(max_val):
                g[x ^ j] = min(g[x ^ j], f[j] - cx)
        f = [val + t2 for val, t2 in zip(g, [cnt[x] for x in range(max_val)])]
        # print(f, g)
  
    return f[0]
总结

以上两种方法都是在遍历数组的基础上,通过不同的思路进行修改。哈希表方法适用于小规模数据,时间复杂度为 O(nk),空间复杂度也是 O(nk);滑动窗口方法适用于大规模数据,时间复杂度为 O(n),空间复杂度为常数级别。