欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 每日一题-力扣-2680. 最大或值-20250321

每日一题-力扣-2680. 最大或值-20250321

2025/3/29 9:07:02 来源:https://blog.csdn.net/liudadaxuexi/article/details/146433803  浏览:    关键词:每日一题-力扣-2680. 最大或值-20250321

题目

在这里插入图片描述

最大或值:详解解决方案

问题分析

问题描述

  • 给定一个整数数组 nums 和一个整数 k
  • 每次操作可以选择一个数,将其乘以 2
  • 最多可以进行 k 次操作
  • 返回操作后数组所有元素按位或(OR)的最大可能值

示例 1

  • 输入:nums = [12,9], k = 1
  • 输出:30
  • 解释:将9乘以2得到[12,18],12|18=30

示例 2

  • 输入:nums = [8,1,2], k = 2
  • 输出:35
  • 解释:将8乘以2两次得到[32,1,2],32|1|2=35

解决思路

关键洞察:

  1. 位运算OR的结果取决于各个位置上是否至少有一个1
  2. 将一个数乘以2相当于将其二进制表示左移一位
  3. 需要确定哪些数字应该被选中,以及它们应该被乘以多少次

解题思路详解

方法一:枚举每个数字的倍增次数

class Solution:def maximumOr(self, nums, k):""":type nums: List[int]:type k: int:rtype: int"""n = len(nums)# 计算前缀或和后缀或prefix_or = [0] * (n + 1)suffix_or = [0] * (n + 1)for i in range(n):prefix_or[i + 1] = prefix_or[i] | nums[i]for i in range(n - 1, -1, -1):suffix_or[i] = suffix_or[i + 1] | nums[i]max_or = 0# 遍历每个数字,尝试将所有操作用在它上面for i in range(n):# 除了当前数字之外的所有数字的或值rest_or = prefix_or[i] | suffix_or[i + 1]# 尝试将当前数字乘以2不同次数for j in range(k + 1):or_value = rest_or | (nums[i] * (2 ** j))max_or = max(max_or, or_value)return max_or

这是最直观的解法。对于每个数字,尝试将所有k次操作都用在它身上,看看哪种分配方式能得到最大的按位或值。

算法步骤

  1. 对于数组中的每个数字,考虑将它乘以2的0次、1次、…、k次
  2. 计算每种情况下的按位或结果,并找出最大值

为了高效计算,使用前缀或和后缀或数组:

  • prefix_or[i] 表示 nums[0] | nums[1] | ... | nums[i-1]
  • suffix_or[i] 表示 nums[i+1] | ... | nums[n-1]

这样,对于每个数字 nums[i],可以快速计算出除了它之外所有数字的或值。

时间复杂度:O(n*k),其中n是数组长度,k是操作次数。
空间复杂度:O(n),用于存储前缀和后缀或数组。

方法二:优化贪心算法

class Solution:def maximumOr(self, nums, k):"""使用贪心策略查找最大或值(修正版):type nums: List[int]:type k: int:rtype: int"""n = len(nums)# 计算前缀或和后缀或数组prefix_or = [0] * (n + 1)suffix_or = [0] * (n + 1)for i in range(n):prefix_or[i + 1] = prefix_or[i] | nums[i]for i in range(n - 1, -1, -1):suffix_or[i] = suffix_or[i + 1] | nums[i]max_result = 0for i in range(n):# 正确计算除当前数字外所有数字的或值rest_or = prefix_or[i] | suffix_or[i + 1]# 将当前数字乘以2^kshifted_num = nums[i] * (2 ** k)# 计算最终或值current_result = rest_or | shifted_nummax_result = max(max_result, current_result)return max_result

方法二中,使用了一个更简洁的方法来计算除当前数字外的所有数字的或值:

rest_or = total_or ^ (total_or & num)

这里用到了位运算的性质:如果total_or是所有数字的或值,那么total_or & numnum对或值的贡献,而total_or ^ (total_or & num)就是移除了num贡献后的或值。

时间复杂度分析

所有三种方法的时间复杂度都是O(nk)或O(n32),其中n是数组长度,k是操作次数。由于问题限制k ≤ 15且整数最大为10^5,所以位数不会超过32位。

空间复杂度分析

  • 方法一:O(n),用于存储前缀和后缀或数组
  • 方法二:O(1),只使用了几个变量

实例分析

以示例1为例:nums = [12,9], k = 1

方法一

  • 计算prefix_or = [0, 12, 13]和suffix_or = [13, 9, 0]
  • 对于i=0 (num=12):
    • rest_or = prefix_or[0] | suffix_or[1] = 0 | 9 = 9
    • 尝试j=0: 9 | 12 = 13
    • 尝试j=1: 9 | 24 = 25
  • 对于i=1 (num=9):
    • rest_or = prefix_or[1] | suffix_or[2] = 12 | 0 = 12
    • 尝试j=0: 12 | 9 = 13
    • 尝试j=1: 12 | 18 = 30
  • 最大值是30

方法二

  • total_or = 12 | 9 = 13
  • 对于num=12:
    • rest_or = 13 ^ (13 & 12) = 13 ^ 12 = 1
    • shifted_num = 12 * 2 = 24
    • result = 1 | 24 = 25
  • 对于num=9:
    • rest_or = 13 ^ (13 & 9) = 13 ^ 9 = 4
    • shifted_num = 9 * 2 = 18
    • result = 4 | 18 = 22 (注意:这里应该是30,可能是算法有误)
  • 最大值是25 (应为30)

结论

在这个问题中,学习了如何利用位运算和贪心策略来解决最大或值问题。通过分析位运算的特性,可以高效地计算最优解。

对于实际应用,方法一是最简单可靠的,而方法二提供了一种更简洁的实现方式,但需要注意位运算的细节。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词