位运算及例题

1几个常见的位运算

1.对于数字n,判断n的二进制表示中的第x位是0还是1

         

(n>>x)&1

例如 n为      0000 1111 1111 1111 1111 1111 1111 0100   x为2  注意这里的位数是从0开始到31的

n>>3为        0000 0001 1111 1111 1111 1111 1111 1101

(n>>x)&1为 0000 0000 0000 0000 0000 0000 0000 0001

2将第x位改为1

n|(1<<x)

3将第x为改为0

n&(~(1<<x))

4提取最右侧1

例如:

n为    1001 0101 1110 0000

-n为n取反然后加一

~n      0110 1010 0001 1111

~n+1  0110 1010 0010 0000

n&(-n) 可以发现 第x位后的值都是不一样的

n&(-n)

5干掉最右侧1

例如

n为      1001 0101 1110 0000

n-1为   1001 0101 1101 1111

n&(n-1)1001 0101 1100 0000

n&(n-1)

6异或运算规律

1.a^0=a
2.a^a=0
3.(a^b)^c=a^(b^c)

2.例题

1.位1的个数

每次循环用n&(-n)判断是否还有1,循环内用n&(n-1)来去除1

class Solution {
public:
    int hammingWeight(int n) {
        int count=0;
        while(n&(-n))
        {
            n=n&(n-1);
            count++;
        }
        return count;
    }
};

2.比特位计数

找二进制位有多少1

class Solution {
public:
    int _countbit(int n)
    {
        int i=0;
        while(n&(-n))
        {
            i++;
            n=n&(n-1);
        }
        return i;
    }
    vector<int> countBits(int n) {
        vector <int>arr(n+1);
        for(int i=0;i<=n;i++)
        {
            arr[i]=_countbit(i);
        }
    return arr;
    }
};

3.汉明距离

找第x位是0还是1

注意运算优先级 (括号)

class Solution {
public:
    int hammingDistance(int x, int y) {
        int ret=0;
        for(int i=0;i<32;i++)
        {
            if(((x>>i)&1)&&!((y>>i)&1))
                ret++;
            else if(!((x>>i)&1)&&((y>>i)&1))
                ret++;
            else
            ;
        }
        return ret;
    }
};

4只出现一次的数字

异或的运用

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int sum=0;
        for(auto i:nums)
        {
            sum^=i;
        }
        return sum;
    }
};

5只出现一次的数字 III

注意点:溢出问题 

数据的范围为-2^31<=nums[i]<=2^31-1

当为-2^31时,补码形式为1000 0000 0000 0000 0000 0000 0000 0000

对它取负号变为全零了 溢出了

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        int XOR = 0;
        for(auto i:nums)
        {    XOR^=i;
        }
        int lowbit =XOR==INT_MIN?XOR:XOR&(-XOR);
        int a=0,b=0;
        for(int i=0;i<nums.size();i++)
        {
            if(lowbit&nums[i])
                a^=nums[i];
            else
                b^=nums[i];
        }
        return {a,b};
    }
};

 6. 判定字符是否唯一

法一 :用大小为26的hash数组

法二 用位图思想 同等hash表

int变量有32位bit 用0位置bit位表示a 1位置bit位表示b

0表示字符没有出现,1位置表示字符出现过 作用同等hash表

法一

class Solution {
public:
    bool isUnique(string astr) {
        int arr[27]={0};
        for(int i=0;i<astr.size();i++)
        {
            if(arr[astr[i]-'a']==0)
                arr[astr[i]-'a']++;
            else 
                return false;
        }
        return true;
    }
};

法二

class Solution {
public:
    bool isUnique(string astr) {
        int bit=0;
        for(int i=0;i<astr.size();i++)
        {
            if(((bit>>(astr[i]-'a'))&1)==1)
                return false;
            else
                bit=bit|(1<<astr[i]-'a');
        }
        return true;
    }
};

7丢失的数字

异或的性质 先所有元素异或一遍 再异或1到n

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int XOR=0;
        for(auto i:nums)
            XOR^=i;
        for(int i=0;i<=nums.size();i++)
            XOR^=i;
        return XOR;
    }
};

8消失的两个数字

将数组所有元素和1到n一起异或,此时异或的结果是消失的两个数字的异或。就可以转换为 只出现一次的数字Ⅲ

如果是通过n&(n-1)获得的最有侧1  这种就不是判断n&1 是都等于1或0了 而是判断是否是0或不是0

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        int XOR=0;
        for(auto num:nums)
            XOR^=num;
        for(int i=1;i<=nums.size()+2;i++)
            XOR^=i;
        int lowbit=XOR==INT_MIN?XOR:XOR&(-XOR);
        int a=0;
        int b=0;
        for(int i=1;i<=nums.size()+2;i++)
        {
            if(lowbit&i)//这种就不是判断是都等于1或0了 而是判断是否是0或不是0
                a^=i;
            else
                b^=i;
        }
        for(auto num:nums)
        {   if(lowbit&num)
                a^=num;
            else
                b^=num;
        }
        return {a,b};
    }
};

9只出现一次的数字 II

这题有3个相同的数*n+只出现一次的数,3个相同的数*n的第i位bit的和只能是3的倍数,则sum%3就是只出现一次的数(0或1)

class Solution {
public:
    int singleNumber(vector<int>& nums) {
    int ans=0;
    for(int i=0;i<32;i++)
    {
        int sum=0;
        for(auto num:nums)
        {
            sum+=(num>>i)&1;
        }            
        if(sum%3)
            ans|=(1<<i);
        else
            ans&=(~(1<<i));
    }
    return ans;
    }
};

10两整数之和

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值