算数通关村第十一关-白银挑战位运算高频题

位移的运算

位1的个数

描述 :

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量)。

题目 :

LeetCode 191.位1的个数

191. 位1的个数

算数通关村第十一关-白银挑战位运算高频题_第1张图片

分析 :

首先我们可以根据题目要求直接计算,题目给定的 n 是 32 位二进制表示下的一个整数,算位1 的个数的最简单的方法是遍历 n 的二进制表示的每一位,判断每一位是否为 1,同时进行计数。

那问题就是如何通过位运算来识别到1,例如: 00001001001000100001100010001001,首先我们注意到要识别到最低位的1,可以这么做 : 

  00001001001000100001100010001001
& 00000000000000000000000000000001
= 00000000000000000000000000000001

也就说将原始数字和1进行&运算就能知道最低位是不是1了,那其他位置怎么算呢? 我们可以有两种思路,让1不断左移或者将原始数据不断右移。例如将原始数据右移就是 :

  00000100100100010000110001000100
& 00000000000000000000000000000001
= 00000000000000000000000000000000

很明显此时就可以判断出第二位是0,然后继续将原始数据右移就可以依次判断出每个位置是不是1了。因此是不是1,计算一下(n>>i) & 1就可以了

解析 :

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int count = 0;
        for(int i = 0;i < 32;i++){
            count += (n >>> i) & 1;
        }
        return count;
    }
}

比特位计算

描述 :

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

题目 :

LeetCode 335.比特位计算 :

338. 比特位计数

算数通关村第十一关-白银挑战位运算高频题_第2张图片

分析 :

这个题目跟上面的题目很像 , 这道题目只在上面题目上加个循环就可以了 . 

解析 : 

暴力解题 :

class Solution {
    public int[] countBits(int n) {
        int[] arr = new int[n + 1];
        for(int i = 0;i <= n;i++){
             for(int j = 0;j < 32;j++){
                 arr[i] += (i >>> j) & 1;
             }
        }
        return arr;
    }
}

位运算解题 :

class Solution {
    public int[] countBits(int n) {
        int[] arr = new int[n + 1];
        for(int i = 0;i <= n;i++){
             arr[i] += count(i);
        }
        return arr;
    }
    public int count(int n){
        int count = 0;
        while(n != 0){
            n = n & (n - 1);
             count++;
        }
        return count;
    }
}

位实现加减乘除专题

在计算机中,位运算的效率比加减乘数效率更高,因此在高性能软件的源码中大量应用,而且计算机里各种运算本质上都是位运算。本专题我们就研究几个相关问题。

两整数之和

题目 :

LeetCode 371.两整数之和 :

371. 两整数之和

分析 :

两个位加的时候,我们无非就考虑两个问题: 进位部分是什么,不进位部分是什么。从上面的结果可以看到,对于a和b两个数不进位部分的情况是: 相同为0,不同为1,这不就是a ^ b吗?

而对于进位,我们发现只有a和b都是1的时候才会进位,而且进位只能是1,这不就是a&b=1吗? 然后位数由1位变成了两位,也就是上面的 4 的样子,那怎么将1向前挪一下呢? 手动移位一下就好了,也就是(a & b) << 1。所以我们得到两条结论:

  • 不进位部分: 用a ^ b计算就可以了。
  • 是否进位,以及进位值使用(a & b ) << 1计算就可以了

解析 :

class Solution {
    public int getSum(int a, int b) {
        while(b != 0){
            int temp = (a & b) << 1;
            a = a ^ b;
            b = temp;
        }
        return a;
    }
}

这期就到这里 , 下期见!

你可能感兴趣的:(算法村,算法,数据结构,java,leetcode)