给你一个整数数组 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