当前位置: 首页 > news >正文

每日一题-力扣-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 = 0
        for i in range(n):
            # 正确计算除当前数字外所有数字的或值
            rest_or = prefix_or[i] | suffix_or[i + 1]
            
            # 将当前数字乘以2^k
            shifted_num = nums[i] * (2 ** k)
            
            # 计算最终或值
            current_result = rest_or | shifted_num
            
            max_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)

结论

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

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

相关文章:

  • 机器学习--DBSCAN聚类算法详解
  • [学习笔记] 部署Docker搭建靶场
  • 机器学习实战
  • 比特币驱动金融第七章——比特币:社区、政治与监管的微妙平衡
  • stratis,容器podman
  • 基于3DMax与Vray引擎的轻量级室内场景渲染实践
  • 校园自习室预约小程序(源码+部署教程)
  • 企业磁盘管理实战:常见问题与高效解决方案
  • Spring6: 2 入门
  • Node.js系列(4)--微服务架构实践
  • next.js 组件路由钩子
  • Linux上位机开发实战(能用的开发板计算资源)
  • 3.9 Spring Boot国际化:动态语言切换与数据库存储方案
  • LabVIEW 与 PLC 通讯的常见方式
  • 大数据学习栈记——HBase安装
  • HashMap学习总结——JDK17
  • PHP 应用TP 框架路由访问对象操作内置过滤绕过核心漏洞
  • STM32-ARM
  • 深入理解 Spring 框架中的 IOC 容器
  • 智能AI优化SEO关键词实战
  • 中方是否认同俄方关于新纳粹主义观点?外交部:联大曾多次通过相关决议
  • 总奖池超百万!第五届七猫现实题材征文大赛颁奖在即
  • 万玲、胡春平调任江西省鹰潭市副市长
  • 央行:全力推进一揽子金融政策加快落地
  • 十四届全国政协原常委、民族和宗教委员会原副主任苟仲文被提起公诉
  • 福特汽车撤回业绩指引,警告关税或造成15亿美元利润损失