题目
2044.统计按位或能得到最大值的子集数目
题目大意
给你一个整数数组 nums
,请你找出 nums
子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。
如果数组 a
可以由数组 b
删除一些元素(或不删除)得到,则认为数组 a
是数组 b
的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。
对数组 a
执行 按位或 ,结果等于 a[0] | a[1]| ...| a[a.length - 1]
(下标从 0 开始)。
样例
数据规模
思路
看到这题第一想法就是对于每个元素nums[i]
选还是不选。再看数据范围1<=nums.length<=16
。那肯定就是直接搜索,时间复杂度O(2^n)
。
定义一个计数器unordered_map<int,int>mp;
用于记录每种结果的数量;定义maxx
记录子集的最大按位或。
函数void dfs(int x,int w,vector<int>& nums)
中x
表示当前枚举第x
个元素(从0开始),一旦x=nums.length
就可以停止往下递归,统计答案,累加结果。每次对于第x
个元素,可以选或者不选,相应的累计按位或的值w
:w|nums[i]
或w
。
最后子集的最大按位或为maxx
,所求的答案就是mp[maxx]
。
代码
// short int long float double bool char string void
// array vector stack queue auto const operator
// class public private static friend extern
// sizeof new delete return cout cin memset malloc
// relloc size length memset malloc relloc size length
// for while if else switch case continue break system
// endl reverse sort swap substr begin end iterator
// namespace include define NULL nullptr exit equals
// index col row arr err left right ans res vec que sta
// state flag ch str max min default charray std
// maxn minn INT_MAX INT_MIN push_back insert
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+50;//注意修改大小
long long read(){long long x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;}
ll qpow(ll x,ll q,ll Mod){ll ans=1;while(q){if(q&1)ans=ans*x%Mod;q>>=1;x=(x*x)%Mod;}return ans%Mod;}
class Solution {
public:
unordered_map<int,int>mp;
int maxx;
void dfs(int x,int w,vector<int>& nums){
if(x==nums.size()){
mp[w]++;
maxx=max(maxx,w);
return;
}
dfs(x+1,w|nums[x],nums);
dfs(x+1,w,nums);
}
int countMaxOrSubsets(vector<int>& nums) {
dfs(0,0,nums);
return mp[maxx];
}
};