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

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

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

LeetCode.2680 最大或值(贪心+前后缀分解)_第1张图片

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

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

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

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

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

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

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

        LeetCode.2680 最大或值(贪心+前后缀分解)_第2张图片

   代码如下:

class Solution {
public:
    typedef long long LL; 
    long long maximumOr(vector& nums, int k) {
        vectorv(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;iy)return x;
        return y;
    }
};

你可能感兴趣的:(LeetCode集锦,算法,贪心算法)