📅  最后修改于: 2023-12-03 14:49:27.390000             🧑  作者: Mango
在给定一个长度为 n 的数组 nums 和一个整数 k,你需要删除最多 k 个元素,使得剩下的元素的按位或值最小,返回这个最小值。
为了使剩下的元素的按位或值最小,我们需要尽可能地保留高位上的 1,因为一个数的按位或值至少是这个数本身,而且每一位上的 1 都会让这个值更大。
因此,我们可以枚举从高到低第 i 位上是否保留 1。如果保留了这个 1,我们就将所有最高位是 1 且第 i 位是 0 的数从数组中删除,直到数组中剩下的数的按位或值大于等于当前答案(因为如果按位或值小于当前答案,那么我们必须删除更多的数才能使其大于等于当前答案,而这是不利于我们使答案更小的)。最后,如果按位或值小于当前答案,我们就保留这一位上的 1;否则我们就将这一位上的 1 删除。
下面是详细的算法代码:
def minimum_or(nums, k):
n = len(nums)
ans = 0
for i in range(30, -1, -1):
cnt_zero = 0
max_or = 0
cur_or = 0
for j in range(n):
if (nums[j] >> i) & 1 == 1:
cur_or |= nums[j]
else:
cnt_zero += 1
max_or = max(max_or, cur_or)
cur_or = 0
max_or = max(max_or, cur_or)
if max_or < ans | (1 << i):
ans |= 1 << i
elif cnt_zero <= k:
k -= cnt_zero
else:
ans |= 1 << i
k -= k
return ans
时间复杂度:$O(n \log W)$,其中 W 表示元素最大值的位数。在每个位上,我们需要枚举一遍数组并计算按位或值,时间复杂度为 $O(n)$。而最高位有 $\log W$ 个,因此总时间复杂度为 $O(n \log W)$。
空间复杂度:$O(1)$。我们只需要常数个额外的变量来保存一些状态。