2022-02-25Leetcode训练营_位运算

天池训练营链接

天池leetcode训练营

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值