📅  最后修改于: 2023-12-03 15:10:36.129000             🧑  作者: Mango
有一个数组,你需要使用最小数量的替换操作,使得数组中所有元素的按位与(&)都大于一个给定的值K。返回最小替换操作数量。
输入:nums = [1,2,4], k = 2
输出:2
解释: 数组中两个数替换为 3 ,即可满足所有元素的按位与大于 2。
我们要提高按位与的值,需要改变数字二进制位的 0 或 1 。我们需要确定要修改的二进制位位置。如果我们选择一个具有足够小的元素来修改,我们可以最大限度地减少需要更改的位数。
例如,假设我们有数字 0b101101,它与数字 0b111110 的按位与为 0b101100。我们可以看到,我们只需要将最后一位从 0 改为 1,就可以将按位与提升到 0b111110。如果我们需要对每个数字执行这种更改,则可以考虑对具有最大位数的数字进行更改。
我们可以从左到右遍历数组中最大的数字,然后在其最高位中设置 1 。这样,我们可以使其与其他数字的按位与最大化。如果将最大的数字修改为 k 及其更高的数字,则按位与的结果将始终小于 k。
class Solution:
def minimizeXor(self, nums: List[int], k: int) -> int:
if not nums:
return 0
msb = -1
for i in range(len(nums)):
while nums[i] >> (msb+1) != 0:
msb += 1
if msb == -1:
return 0
mask = (1 << (msb+1)) - 1
max_num = -1
for i in range(len(nums)):
if (nums[i] & mask) > max_num:
max_num = nums[i] & mask
if max_num < k:
return msb+1
ans = 0
for i in range(len(nums)):
if (nums[i] & mask) != max_num:
continue
new_num = nums[i] & (mask - 1)
if new_num >= k:
continue
j = 0
while j < msb+1 and ((1 << j) & nums[i]) != 0:
j += 1
if j > msb:
ans = -1
break
nums[i] |= 1 << j
ans += 1
max_num = max(max_num, nums[i] & mask)
if max_num >= k:
break
if max_num < k:
ans = -1
return ans
本题可以看做是一道贪心算法的题目,采用从左到右遍历数组中最大的数字,然后在其最高位中设置 1 ,使其与其他数字的按位与最大化,最后判断是否有任意数字的 new_num < k,如果有则 ans = -1,否则返回 ans 的值。