[题解]《算法零基础100讲》(第42讲) 位运算 (位与) 入门

一. 概念讲解

1.1 位与运算

  按位与运算是对两个二进制数的每一位进行与判断的运算,同为1则为1,否则为0。

运算方式:

x y x & y
1 1 1
0 1 0
1 0 0
0 0 0

1.2 奇偶判断

我们先看一个表格;

奇偶性 末尾数字
奇数 1
偶数 0

  通过这个表格我们很容易发现,可以用&运算判断奇偶,由于我们只需判断末尾的数字即可,假设一个变量为x,则x & 1 == 0则说明为偶数,否则为奇数。

假设x = 7,则计算x & 1如下:
1 1 1
0 0 1
0 0 1 => 1
所以可以判断出x为奇数

代码演示:

if(x & 1){
    
    
	printf("x为奇数\n");
}
else{
    
    
	printf("x为偶数\n");
}

1.3 取末尾数字

  由上面的例子我们发现,通过&1可以得出第一位数字,所以我们通过&010可以得到第二位上的数字,以此类推。通过此方法我们可以得出末尾k位数字。

我们通过代码取出末尾五个数字:

#include <stdio.h>

int main(){
    
    
	int x;
	scanf("%d", &x);
	printf("%d\n", x & 0b11111);
	return 0;
}

这里0b是指二进制的意思。

1.4 消除末尾几位

  我们可以通过对最大的数字进行&运算得到的是其本身。

0000 0000 0000 0000 0000 0000 0000 0111
1111 1111 11111 1111 1111 1111 1111 1111
0000 0000 0000 0000 0000 0000 0000 0111

如果我们要消除末尾第一位的话只需将最大的数末尾改为0即可,

0000 0000 0000 0000 0000 0000 0000 0111
1111 1111 11111 1111 1111 1111 1111 1110
0000 0000 0000 0000 0000 0000 0000 0110

以此类推。

代码如下:

#include <stdio.h>
int main() {
    
    
    int x;
    scanf("%d", &x);
    printf("%d\n", (x & 0xffffffe0) );
    return 0;
} 

1.5 判断2的幂

  2的幂减1&其本身的结果一定位0(自行理解)

例如 10000000 与 01111111 结果是0

x & (x - 1)

二. 推荐专栏

《算法零基础100讲》(第42讲) 位运算 (位与) 入门

三. 相关练习

3.1 位1的个数

题目链接:

191. 位1的个数

思路分析:

我们通过计算2的幂的方式,每次&(n - 1)都会消去最后面的1,计算循环次数。

代码如下:

int hammingWeight(uint32_t n) {
    
    
    int count = 0;
    while(n){
    
    
        n = n & (n - 1);//消去当前最低为的1
        count ++;
    }
    return count;
}

3.2 根据数字二进制下 1 的数目排序

1356. 根据数字二进制下 1 的数目排序

思路分析:

我们先通过上面的方法将数组arr内所有元素的二进制中1的数量计算出来,并对应下标存放再数组bit中,然后我们使用qsort函数对其进行排序,根据其对应bit中的大小来排。

代码如下:

int* bit;

int get(int n){
    
    
    int cnt = 0;
    while(n){
    
    
        n = n & (n - 1);
        cnt++;
    }
    return cnt;
}

int cmp(const void* a, const void* b){
    
    
    int x = *(int*)a;
    int y = *(int*)b;
    return bit[x] == bit[y] ? x - y : bit[x] - bit[y];
}

int* sortByBits(int* arr, int arrSize, int* returnSize){
    
    
    bit = (int*)malloc(sizeof(int) * 10001);
    memset(bit, 0, sizeof(bit));
    for(int i = 0; i < arrSize; i++){
    
    
        bit[arr[i]] = get(arr[i]);
    }
    qsort(arr, arrSize, sizeof(int), cmp);
    *returnSize = arrSize;
    return arr;
}

3.3 二进制表示中质数个计算置位

762. 二进制表示中质数个计算置位

思路分析:

题目要求我们计算一个人数组内每个元素二进制表示中1的个数是质数的数量,计算1的个数我们可以用kk = kk & (kk - 1)来计算,然后再判断是否位质数。

代码如下:

bool judge(int n){
    
    
    if(n < 2)return false;
    for(int i = 2; i * i <= n; i++){
    
    
        if(n % i == 0)return false;
    }
    return true;
}

int countPrimeSetBits(int left, int right){
    
    
    int ans = 0;
    for(int i = left; i <= right; i++){
    
    
        int cnt = 0;
        int kk = i;
        while(kk){
    
    
            kk = kk & (kk - 1);//计算1的个数
            cnt++;
        }
        if(judge(cnt)){
    
    
            ans++;
        }
    }
    return ans;
}

3.4 的幂

231. 2 的幂

思路分析:

这道题我们就用上面的知识点判断,n & (n - 1)。

代码如下:

bool isPowerOfTwo(int n){
    
    
    if(n <=0 ) return false;
    return !(n &(n-1));
}

Guess you like

Origin blog.csdn.net/qq_53060585/article/details/121725582