【Leetcoe】2680. 最大或值_1912

题目

2680. 最大或值

给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 k 。每一次操作中,你可以选择一个数并将它乘 2 。

你最多可以进行 k 次操作,请你返回 nums[0] | nums[1] | ... | nums[n - 1] 的最大值。

a | b 表示两个整数 a 和 b 的 按位或 运算。

  • \(1<=nums.length<=10^5\)

前言

一道前缀和加上一点脑筋急转弯,(其实也可以说是贪心)

思路

首先可以明确的是,乘2的机会都会给到同一个数字,且这个数字拥有最长的二进制位。

对于或运算,乘2就是所有的二进制左移。如果此时选取二进制最长的进行左移,那么此时的最高位就会越来越大,而选取二进制较短的进行左移或者不是所有的左移都给到同一个数字上,就会导致最高位的1总是不超过选取最长二进制进行左移的位置。

若同时存在多个数字其二进制长度相等,此时就不好确定具体是哪个了。

考虑使用 前缀和 和 后缀和 ,分别用以记录前缀和后缀的异或值。

class Solution:
    def maximumOr(self, nums: List[int], k: int) -> int:
        pref = [0] # prer[i] 表示 nums[:i] 的或值
        suff = [0] # suff[i] 表示 nums[n-i:] 的或值
        n = len(nums)
        for i in range(n):
            pref.append(pref[-1] | nums[i])
            suff.append(suff[-1] | nums[n - 1 - i])
        ans = 0
        for i in range(n):
            ans = max(ans, pref[i]|(nums[i]<<k)|suff[n-i-1])
        return ans

上述代码的时间复杂度为\(O(n)\),空间复杂度为\(O(n)\)

但是可以发现的是,进行了两次循环,而每次前缀异或也只是利用到最后的这个,因此可以将前缀的操作放到第二层循环里,使得空间复杂度降低。

class Solution:
    def maximumOr(self, nums: List[int], k: int) -> int:
        suff = [0] # suff[i] 表示 nums[n-i:] 的或值
        n = len(nums)
        for i in range(n):
            suff.append(suff[-1] | nums[n - 1 - i])
        ans = 0
        pre = 0
        for i in range(n):
            ans = max(ans, pre|(nums[i]<<k)|suff[n-i-1])
            pre|=nums[i]
        return ans
posted @ 2024-09-10 15:19  TICSMC  阅读(8)  评论(0)    收藏  举报