LeetCode.2680 最大或值(贪心+前后缀分解)

题目链接如下:https://leetcode.cn/problems/maximum-or/

该题用到了贪心+前后缀分解的方法(对于我这个小白来说挺难想的)

 关于前导知识:一个数乘以2相当于一个数左移1位,比如对于2,它的二进制为10,左移以为相当于100,为4,我们可以根据C++语言中<<符号来实现该情况,

        举例说明:int x=2,y; y=x<<1;则y=4;

        同理:对于一个数来说,如果移动k位,则可以如下来写: int x=2,y; y=x<<k;

回到该题,我们可以这样分析,对于nums数组,假如一个数在这些数中的二进制位数最大,我们就一直可以让它左移,由于是或运算,不存在进一的情况,选中一个最大值,一直左移取或运算就可以取得最大值,根据贪心策略,如果选中一个数一直取左移,可以得到取或的最大值。

当然,这一步肯定好想,但是对于二进制位数相同的情况呢,对于题中案例的9和12,并不选择12,而是选择9,我们可以将其拆分成二进制12 —> 1100,9—>1001,发现如果9左移后取或较大,

下面就开始拆解二进制了.

        请看示例:我们可以定义一个数组来维护后缀表达式(即维护第i位及之后的取或运算),定义一个前缀中间变量,用来维护i位之前(不包含i)的取或运算,通过取第i位数的左移位运算,设置中间变量,取得最大值,图解如下(三段论):

        

   代码如下:

class Solution {
public:
    typedef long long LL; 
    long long maximumOr(vector<int>& nums, int k) {
        vector<LL>v(nums.size()+1);
        for(int i=nums.size()-1;i>=0;i--)v[i]=v[i+1]|nums[i];//维护后缀表达式
        LL ans=-1;//定义结果
        LL tmp=0;//定义前缀表达式
        for(int i=0;i<nums.size();i++){
            ans=max(ans,tmp|((LL)nums[i]<<k)|v[i+1]);//更新三段
            tmp|=nums[i];//前缀表达式
        }
        return ans;
    }
    LL max(LL x,LL y){
        if(x>y)return x;
        return y;
    }
};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

打铁柒柒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值