最小无法得到的或值

标签: 位运算 脑筋急转弯 数组

难度: Medium

给你一个下标从 0 开始的整数数组 nums 。

如果存在一些整数满足 0 <= index1 < index2 < ... < indexk < nums.length ,得到 nums[index1] | nums[index2] | ... | nums[indexk] = x ,那么我们说 x 是 可表达的 。换言之,如果一个整数能由 nums 的某个子序列的或运算得到,那么它就是可表达的。

请你返回 nums 不可表达的 最小非零整数 。

示例 1:

输入:nums = [2,1]
输出:4
解释:1 和 2 已经在数组中,因为 nums[0] | nums[1] = 2 | 1 = 3 ,所以 3 是可表达的。由于 4 是不可表达的,所以我们返回 4 。

示例 2:

输入:nums = [5,3,2]
输出:1
解释:1 是最小不可表达的数字。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109

Submission

运行时间: 43 ms

内存: 28.3 MB

class Solution:
    def minImpossibleOR(self, nums: List[int]) -> int:
        mask = 0
        for x in nums:
            if x&(x-1)==0:
                mask |= x
        mask = ~mask
        return mask&-mask

Explain

该题解采用了位运算的方法来寻找最小无法得到的或值。首先,它检查数组中的每个数是否是2的幂(即只有一个位是1),这是通过判断x & (x - 1) == 0来实现的,因为只有2的幂和零才能满足这一点。随后,将这些2的幂通过或运算累积到mask变量中。最后,通过取mask的补码,并与其补码的相反数进行与运算,得到最低位的1,这个最低位的1代表的就是最小的无法通过给定数组的子序列得到的非零整数。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def minImpossibleOR(self, nums: List[int]) -> int:
        mask = 0
        # 遍历所有数字,检查是否为2的幂
        for x in nums:
            if x & (x - 1) == 0:  # x是2的幂
                mask |= x  # 累积所有2的幂的或运算结果
        mask = ~mask  # 取反,找出没有出现的2的幂
        return mask & -mask  # 返回最低位的1,即最小的未出现的2的幂

Explore

题解采用的方法仅针对2的幂进行检测和处理,而实际上非2的幂的数在进行或运算时可以产生包含多个位为1的结果,这可能会生成一些额外的可表达的或值。因此,忽略非2的幂的数可能会导致漏掉一些由这些数与其他数或运算生成的可表达的或值,从而影响找到真正的最小无法得到的或值。

题解中只考虑2的幂是因为2的幂在二进制表示中只有一个位是1,它们在或运算中的行为比较特殊且容易分析。但实际上,多个数的或运算可能会生成新的可表达的或值,尤其是当这些数的二进制表示中有多个位是1时。因此,只考虑2的幂可能会忽略掉由非2的幂数通过组合产生的可表达的或值,这可能导致无法正确找到真正的最小无法得到的或值。

这种方法只能保证找到未通过数组中的2的幂子序列得到的最小的非零整数,因为它只考虑了2的幂。如果数组中存在非2的幂的数或其组合能产生新的可表达的或值,这种方法可能会错过这些通过非2的幂数组合得到的可表达值。因此,这种方法在数组包含非2的幂的情况下并不能确保总是找到所有未通过数组子序列得到的非零整数中的最小值。