天池训练营链接
2的幂
题解链接
有符号整数,最大的2的幂是2^30 ,所以只需判断是不是2^30的因子。
class Solution {
public:
bool isPowerOfTwo(int n) {
int BIG= 1<<30;
return n>0 && BIG%n==0;
}
};
n&(n-1)能去掉二进制最低位的1,n&(n-1)=0的话就是2的幂
return n>0 && ((n-1)&n) ==0;
//这几个括号不知道啥情况,不加会报错
只出现一次的数字
哈希集合法,时间O(n),空间大
class Solution {
public:
int singleNumber(vector<int>& nums) {
//哈希集合
unordered_set<int> s;
//扫描,如果在集合里面,就删掉,否则,进集合,最后剩的就是只出现1次的
for(auto i:nums){
if(s.count(i)){
s.erase(i);
}
else(s.insert(i));
}
int ans;
for(auto i=s.begin(); i!=s.end(); ++i){
ans=*i;
//注意这个迭代
}
return ans;
}
};
位运算法
0和任何数异或都等于那个数,a和a异或等于0
所以nums里面的数全异或了以后,最后得到的就是只出现一次的数
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans=0;
for(auto i:nums){
ans=ans ^ i;
}
return ans;
}
};
只出现一次的数字 II
参考题解
有限状态机可以看一下。
思路1:
哈希表,用unordered_map,[数字,次数],里面是初始化0的。
class Solution {
public:
int singleNumber(vector<int>& nums) {
unordered_map<int,int> m;
int ans=0;
for(auto i:nums){
++m[i];
}
for(auto [num, freq]: m){
if(freq==1){
ans=num;
break;
}
} //return ans;
return ans;
}
};
思路2:逐个位相加,模3取余,一共32位,时间复杂度O(n)
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans=0;
for(int i=0; i<32;++i){
int total=0;
for(auto num:nums){
total+=((num>>i)&1);
}
if(total%3){
ans |= (1<<i);
}
}
return ans;
}
};
只出现一次的数字 III
题解链接
直接看题解吧
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int xorsum=0;
for(int num:nums){
xorsum ^= num;
}
int lsb=(xorsum==INT_MIN ? xorsum : xorsum & (-xorsum));
int type1=0,type2=0;
for(int num:nums){
if(num & lsb){
type1 ^= num;
}
else{
type2 ^= num;
}
}
return {type1, type2};
}
};
子集
要回顾
思路一:位运算
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
int n=nums.size();
vector<int> v;
vector<vector<int>> ans;
int mask=0;
for(int mask=0; mask<(1<<n); ++mask){
//用mask来枚举每个子集的状态
v.clear();
for(int i=0; i<n; ++i){
if(mask & (1<<i)){
//对照题解中的表,mask取1的位代表这位被选进来v
//比如mask是0101的时候,位是0123,1和3位被选中,nums有4个数,这次nums[1]和nums[3]进v
v.push_back(nums[i]);
}
}
ans.push_back(v);
}
return ans;
}
};
思路二:DFS
其实是动规的思路
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
void dfs(int cur, vector<int>& nums){
if(cur==nums.size()){
ans.push_back(t);
return;
}
t.push_back(nums[cur]);
dfs(cur+1, nums);
t.pop_back();
dfs(cur+1, nums);
//注意这里,不能先做不选cur,否则会遇到同步问题,
//如果不用pop的话
//dfs(cur+1, nums); t.push_back(nums[cur]); dfs(cur+1, cur)
//这样dfs可能和下面的push_back同时执行,结果会乱掉
}
vector<vector<int>> subsets(vector<int>& nums) {
dfs(0,nums);
return ans;
}
};
知识
- n&(n-1)能去掉n二进制最低位的1,n&(n-1)=0的话就是2的幂
//迭代unordered_set
for(auto i=s.begin(); i!=s.end(); ++i){
ans=*i;
//注意这个迭代
}
- 异或,0和任何数异或都等于那个数,a和a异或等于0
- unordered_map,初始化和遍历
unordered_map<int,int> m;
int ans=0;
for(auto i:nums){
++m[i];
}
for(auto [num, freq]: m){
if(freq==1){
ans=num;
break;
}
} //return ans;
- x&(-x)返回最低位的1,用于 只出现一次的数字 III