2044. 统计按位或能得到最大值的子集数目

给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。

如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。

对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR ... OR a[a.length - 1](下标从 0 开始)。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例 :

输入:nums = [3,2,1,5]
输出:6
解释:子集按位或可能的最大值是 7 。有 6 个子集按位或可以得到 7 :
- [3,5]
- [3,1,5]
- [3,2,5]
- [3,2,1,5]
- [2,5]
- [2,1,5]

考点:

按位或运算

bitmap在遍历中的应用

class Solution(object):
    def countMaxOrSubsets(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        max = 0
        n = len(nums)

        s_num = 0  #记录所有的子集按位与结果的最大值
        for s in range(1 << n):  #把1按比特位左移n位的值 等于 2的n次方数值。
            #遍历2的n次方个子集,计算出该子集按位与的最大值
            #一开始怎么知道一共有多少个子集的呢?就是排列组合,选不选list中的某个index的数据,
            #选的话,对应比特位置为1,不选置为0,则所有的排列组合个数为2的n次方:每个bit都可以是
            #0或1;一共n位,其中一个非空子集,一个全集,全集不算,所以不遍历2的n次方这个全子集
            #怎么当前子集计算按位与的值?重点在于把当前的子集的编号,对应回bitmap.[01010000..]
            #比如第2个子集,bitmap是[0000..000010]
            sum = 0
            for i in range(n):#i遍历的是当前子集S对应的bitmap里的各个index,bitmap长度总为n
                if (s >> i) & 1 == 1:
                    #s是当前子集的序号,也对应于一个bitmap.右移i位与1与为1的话说明
                    #第i位上的元素被选中了,这个i也对应原list中的index
                    #在这子集中,
                    #选了原list中的第i个元素,这个循环等于在遍历这个子集中的所有元素
                    #只不过是对应于原list中的元素
                    #那么这个原list中的第i个元素参与按位或|=,并记录到按位或
                    #注意 一个list元素按位或的最大值就是所有元素参与按位或的值
                    #把选中的i位的元素拿出来连续取与
                    sum |= nums[i]
            if sum > max:#与其他的子集的按位或值比较,记录下最大的值
                s_num = 1
                max = sum#获得了一个按位或值更大的一个子集

            elif sum == max:
                s_num += 1#获得了又一个按位或值最大的子集,个数加上1

        return s_num

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值