📜  要在给定数组中完成的最小删除操作,使得每对总和都是 2 的幂(1)

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

在给定数组中完成的最小删除操作,使得每对总和都是2的幂

问题描述

给定一个不为空的整数数组,你需要找到最小的删除操作使得对于任意一对不同的元素 $a_i$ 和 $a_j$,都满足 $a_i + a_j$ 是 2 的幂次方。返回最小的删除操作数。

示例
输入: [1,2,3,4,5,6,7,8,9,10]
输出: 2
解释: 可以删除 3 和 5,使得剩下的元素为 [1, 2, 4, 6, 7, 8, 9, 10],任意一对元素的和都是 2 的幂次方。
解决方案

我们可以先用一个循环嵌套计算出每对元素的和,然后判断每对元素的和是否是 2 的幂。如果有一对元素的和不满足条件,我们就将其中一个元素从数组中删除,然后继续计算,直到所有的元素对的和都满足条件为止。最终我们需要删除的元素个数就是删除操作数。

这种解决方案的时间复杂度为 $O(n^2)$,对于较大的数组可能会很耗时。如果我们能够快速计算出每个元素和能够组成的 2 的幂,就能够优化解决方案。

我们可以用一个哈希表来记录所有能够组成 2 的幂的数字和对应的元素。然后我们用一个循环遍历整个数组,并计算出每个元素和能够组成的 2 的幂,然后在哈希表中查找是否有相应的数字和元素。如果没有,那么我们就将该元素加入哈希表。如果有,那么我们就将该元素从数组中删除,并更新删除操作数。最终的删除操作数即为所求。

代码实现
def minDeletions(nums: List[int]) -> int:
    freq = {}
    res = 0
    for num in nums:
        count = 0
        while num % 2 == 0:
            num //= 2
            count += 1
        if count in freq:
            while count in freq and freq[count]:
                count += 1
                res += 1
            if count not in freq:
                freq[count] = 1
            else:
                freq[count] += 1
        else:
            freq[count] = 1
    return res
复杂度分析

时间复杂度:$O(nlog n)$,其中 $n$ 是给定数组的长度。循环遍历整个数组需要 $O(n)$ 的时间,每次计算一个元素和能够组成的 2 的幂需要 $O(log n)$ 的时间,查询或更新哈希表需要 $O(1)$ 的时间,因此总时间复杂度为 $O(nlog n)$。

空间复杂度:$O(n)$,其中 $n$ 是给定数组的长度。需要用哈希表记录每个元素和能够组成的 2 的幂,哈希表的大小不能超过 $n$。