📌  相关文章
📜  在数组之一中获得多数元素所需的相同索引元素的最小交换(1)

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

在数组之一中获得多数元素所需的相同索引元素的最小交换

在一个整数数组中,多数元素是指在数组中出现次数超过一半的元素。现在给定一个数组,你的任务是找到一个元素 x,使得在数组中出现次数超过一半的元素就是 x。同时,你需要找出需要交换的最小元素个数,使得这个元素 x 的出现次数满足要求。

例如,给定数组 nums = [1,2,3,1,1,1],元素 1 在数组中出现了 4 次,超过了数组长度的一半。因此我们可以找到元素 x = 1 并且最小交换次数为 2,即交换数组中第 2 个和第 4 个元素,和第 2 个和第 5 个元素,可以使得元素 1 的出现次数达到 4 次。

解法

要找到多数元素,可以先对数组进行排序,然后找到排序后数组中间的元素。由于多数元素的定义,这个中间元素一定是多数元素。

接下来,我们需要统计数组中元素出现的次数,并计算交换次数。给定元素 x,我们可以使用哈希表来记录 x 在数组中出现的所有位置,然后在哈希表中查找需要交换的元素。

例如,对于数组 nums = [1,2,3,1,1,1],当 x = 1 时,哈希表中记录的元素和位置为 {1: [0, 3, 4, 5]},即元素 1 出现在数组中的位置为 0、3、4、5。为了使出现次数超过一半的元素是 x,我们需要交换数组中一些元素,使得最终数组中有 4 个元素是 x。

为了达到这个目的,我们可以从前往后遍历数组,并记录当前出现的 x 的个数 cnt。如果遇到 x 的位置不在哈希表中,我们需要从队列中取出一个位置和当前位置交换,这样才能保证交换后 x 的个数会增加。如果队列为空,说明无法完成这个目标,直接返回 -1。

代码
import collections

def min_swap(nums):
    n = len(nums)
    if n < 2:
        return -1 # 数组太小,无法完成目标

    # 找到多数元素
    nums.sort()
    x = nums[n // 2]

    # 统计 x 在数组中出现的位置
    pos = collections.defaultdict(list)
    for i in range(n):
        if nums[i] == x:
            pos[x].append(i)

    # 遍历数组,计算交换次数
    cnt, ans = 0, 0
    for i in range(n):
        if nums[i] == x:
            cnt += 1
            if cnt > n // 2:
                break
        elif pos[x]:
            ans += 1
            pos[x].pop(0)
            cnt += 1

    return ans if cnt > n // 2 else -1