📌  相关文章
📜  最小化 Array 元素的替换以使按位与大于 K(1)

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

最小化 Array 元素的替换以使按位与大于 K

有一个数组,你需要使用最小数量的替换操作,使得数组中所有元素的按位与(&)都大于一个给定的值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
复杂度分析:
  • 时间复杂度:O(n log n),其中 n 是数组的长度。最坏情况下,我们需要对长度为 n 的数组进行排序。
  • 空间复杂度:O(log n)。我们需要保存排序后的数字。
总结

本题可以看做是一道贪心算法的题目,采用从左到右遍历数组中最大的数字,然后在其最高位中设置 1 ,使其与其他数字的按位与最大化,最后判断是否有任意数字的 new_num < k,如果有则 ans = -1,否则返回 ans 的值。