数据结构☞位运算


在这里插入图片描述

一、含义

1、常用位操作

1)判断奇偶性:
(x & 1)== 1 等价于(x % 2 == 1)奇数
(x & 1)== 0 等价于(x % 2 == 0)偶数
2)x / 2 等价于 x>>1
3)x &=(x - 1)等价于 把x最低位的二进制1给去掉
4)x & -x 等价于 x & (~x+1) 即得到最低位1
5)x & ~x 等于 0
6)~0:表示全为1的数
7)0与任何数异或 = 原数;相同的两个数异或 = 0

2、指定位置的位运算

1)将 x 最右边的 n 位清零:x & (~0 << n)
2)获取 x 的第 n 位值:(x >> n)& 1
3)获取 x 的第 n 位的幂值:x & (1 << n)
4)仅将第 n 位置为 1:x |=(1<<n)
5)仅将第 n 位置为 0:x |=(~(1<<n))
6)将 x 最高位至第 n 位(含)清零:x & ((1 << n) - 1)
7)将第 n 位至第 0 位(含)清零:x &(~((1 << (n + 1)) - 1))

二、题解

1、191. 位1的个数

方法一:
1)当一个数被减1时,它最右边的那个值为1的bit将变为0,同时其右边的所有的bit都会变成1
2)每次执行n&(n-1)的作用就是把x对应的二进制数中的最后一位1去掉。因此,循环执行这个操作直到x等于0的时候,循环的次数就是x对应的二进制数中1的个数。

方法二:
通过 n & 1 ( n % 2)来统计当前 n 的最低位是否为1,同时每次直接对n进行右移并高位补0

#include<stdio.h>

int func(int x)
{
    int countx = 0;
    while(x)
    {
        countx++;
        x &= x-1;
        //count += (n & 1); // n % 2
        //n >>= 1;
    }
    return countx;
}

int main(void)
{
    int n = 9;
    printf("%d里有%d个1\n",n ,func(n));
    
    return 0;
}

2、求解二进制中0的个数

在这里插入图片描述

#include<stdio.h>

int ZeroNum(int n)
{
    int count = 0;
    while(n+1)
    {
        count++;
        n |= (n+1);
    }
    return count;
}

int main(void)
{
    int value = 25;
    int ret = ZeroNum(value);
    printf("%d中有%d个0\n",value, ret);
    return 0;
}

3、设置或清除某一位的值

给定一个变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3.在以上两个操作中,要保持其他位不变。

#include<stdio.h>

#define BIT3 (0x1<<3)
static int a;

/*设置bit3*/
void set_bit3(void)
{
    a |= BIT3;
}

/*清除bit3*/
void clear_bit3(void)
{
    a &= ~BIT3;
}

4、136. 只出现一次的数字

方法一:异或法
0与任何数异或 = 原数
相同的两个数异或 = 0

方法二:哈希表map< key, value >
1、遍历一遍数组,将所有元素插入到哈希表中;
2、遍历数组,如果该元素对应的键值 == 1,则返回该元素。

方法三:集合set< int >
1、遍历整个数组,如果集合中存在该元素,就将其删除,否则将其插入到该集合中;
2、最终该集合中只有一个元素,返回集合首元素。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
    //异或法
        int ret = 0;
        for(auto x : nums){
            ret ^= x;
        }
        return ret;
    }
};
class Solution {
public:
    int singleNumber(vector<int>& nums) {
    //哈希表map
        unordered_map<int , int>map;
        for(auto i : nums) map[i]++;
        for(auto i : nums) {
            if(map[i] == 1) return i;
        }
        return 0;
    }
};
class Solution {
public:
    int singleNumber(vector<int>& nums) {
    //集合set
        unordered_set<int>set;
        for(auto i : nums){
            if(set.count(i) == 1) {
                set.erase(i);
            }else{
                set.insert(i);
            }
        }
        return *set.begin();
    }
};

5、231. 2 的幂

恒有 n & (n - 1) == 0
恒有 n & (-n) == n

class Solution {
public:
    bool isPowerOfTwo(int n) {
        // return (n > 0 && (n&(n-1)) == 0);
        return (n > 0 && (n&(-n)) == n);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值