打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
425,剑指 Offer-二进制中1的个数

Success at anything will always come down to this: Focus & Effort, and we control both. 

任何事物的成功都取决于两方面:专注和努力,而两者都由我们控制。

问题描述



请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。

例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。

示例 1:

输入:00000000000000000000000000001011

输出:3

解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。

示例 2:

输入:00000000000000000000000010000000

输出:1

解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。

示例 3:

输入:11111111111111111111111111111101

输出:31

解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。

二进制中1的个数



这道题是剑指offer上的一道题,其实比较简单,但要写10种以上的解法估计不容易,之前专门分3个系列讲过二进制中1的个数

364,位1的个数系列(一)

385,位1的个数系列(二)

402,位1的个数系列(三)

前面已经写过了,这里就不在细写了,我把答案全部列出来,因为太多,我只给一些简单的提示,如果不懂的可以看下前面写的那3个系列,或者也可以在下面留言,我来给你解答。

1,把n往右移32次,每次都和1进行与运算

1public int hammingWeight(int n) {
2    int count = 0;
3    for (int i = 0; i < 32; i++) {
4        if (((n >>> i) & 1) == 1) {
5            count++;
6        }
7    }
8    return count;
9}

2,原理和上面一样,做了一点优化

1public int hammingWeight(int n) {
2    int count = 0;
3    while (n != 0) {
4        count += n & 1;
5        n = n >>> 1;
6    }
7    return count;
8}

3,1每次往左移一位,再和n进行与运算

1public int hammingWeight(int n) {
2    int count = 0;
3    for (int i = 0; i < 32; i++) {
4        if ((n & (1 << i)) != 0) {
5            count++;
6        }
7    }
8    return count;
9}

4,1每次往左移一位,把运算的结果在右移判断是否是1

1public int hammingWeight(int i) {
2    int count = 0;
3    for (int j = 0; j < 32; j++) {
4        if ((i & (1 << j)) >>> j == 1)
5            count++;
6    }
7    return count;
8}

5,这个是最常见的,每次消去最右边的1,直到消完为止

1public int hammingWeight(int n) {
2    int count = 0;
3    while (n != 0) {
4        n &= n - 1;
5        count++;
6    }
7    return count;
8}

6,把上面的改为递归

1public int hammingWeight(int n) {
2    return n == 0 ? 0 : 1 + hammingWeight(n & (n - 1));
3}

7,查表

 1public int hammingWeight(int i) {
2    //table是0到15转化为二进制时1的个数
3    int table[] = {0112122312232334};
4    int count = 0;
5    while (i != 0) {//通过每4位计算一次,求出包含1的个数
6        count += table[i & 0xf];
7        i >>>= 4;
8    }
9    return count;
10}

8,每两位存储,使用加法(先运算再移位)

1public int hammingWeight(int n) {
2    n = ((n & 0xaaaaaaaa) >>> 1) + (n & 0x55555555);
3    n = ((n & 0xcccccccc) >>> 2) + (n & 0x33333333);
4    n = (((n & 0xf0f0f0f0) >>> 4) + (n & 0x0f0f0f0f));
5    n = n + (n >>> 8);
6    n = n +  (n >>> 16);
7    return n & 63;
8}

9,每两位存储,使用加法(先移位再运算)

1public int hammingWeight(int n) {
2    n = ((n >>> 1) & 0x55555555) + (n & 0x55555555);
3    n = ((n >>> 2) & 0x33333333) + (n & 0x33333333);
4    n = (((n >>> 4) & 0x0f0f0f0f) + (n & 0x0f0f0f0f));
5    n = n + (n >>> 8);
6    n = n + (n >>> 16);
7    return n & 63;
8}

10,和第8种思路差不多,只不过在最后几行计算的时候过滤的比较干净

1public int hammingWeight(int n) {
2    n = ((n & 0xaaaaaaaa) >>> 1) + (n & 0x55555555);
3    n = ((n & 0xcccccccc) >>> 2) + (n & 0x33333333);
4    n = (((n & 0xf0f0f0f0) >>> 4) + (n & 0x0f0f0f0f));
5    n = (((n & 0xff00ff00) >>> 8) + (n & 0x00ff00ff));
6    n = (((n & 0xffff0000) >>> 16) + (n & 0x0000ffff));
7    return n;
8}

11,每4位存储,使用加法

1public int hammingWeight(int n) {
2    n = (n & 0x11111111) + ((n >>> 1) & 0x11111111) + ((n >>> 2) & 0x11111111) + ((n >>> 3) & 0x11111111);
3    n = (((n & 0xf0f0f0f0) >>> 4) + (n & 0x0f0f0f0f));
4    n = n + (n >>> 8);
5    n = n + (n >>> 16);
6    return n & 63;
7}

12,每3位存储,使用加法

1public int hammingWeight(int n) {
2    n = (n & 011111111111) + ((n >>> 1) & 011111111111) + ((n >>> 2) & 011111111111);
3    n = ((n + (n >>> 3)) & 030707070707);
4    n = ((n + (n >>> 6)) & 07700770077);
5    n = ((n + (n >>> 12)) & 037700007777);
6    return ((n + (n >>> 24))) & 63;
7}

13,每5位存储,使用加法

1public int hammingWeight(int n) {
2    n = (n & 0x42108421) + ((n >>> 1) & 0x42108421) + ((n >>> 2) & 0x42108421) + ((n >>> 3) & 0x42108421) + ((n >>> 4) & 0x42108421);
3    n = ((n + (n >>> 5)) & 0xc1f07c1f);
4    n = ((n + (n >>> 10) + (n >>> 20) + (n >>> 30)) & 63);
5    return n;
6}

14,每两位存储,使用减法(先运算再移位)

1public int hammingWeight(int i) {
2    i = i - ((i >>> 1) & 0x55555555);
3    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
4    i = (i + (i >>> 4)) & 0x0f0f0f0f;
5    i = i + (i >>> 8);
6    i = i + (i >>> 16);
7    return i & 0x3f;
8}

15,每3位存储,使用减法

1public int hammingWeight(int n) {
2    n = n - ((n >>> 1) & 033333333333) - ((n >>> 2) & 011111111111);
3    n = ((n + (n >>> 3)) & 030707070707);
4    n = ((n + (n >>> 6)) & 07700770077);
5    n = ((n + (n >>> 12)) & 037700007777);
6    return ((n + (n >>> 24))) & 63;
7}

16,每4位存储,使用减法

1public int hammingWeight(int n) {
2    int tmp = n - ((n >>> 1) & 0x77777777) - ((n >>> 2) & 0x33333333) - ((n >>> 3) & 0x11111111);
3    tmp = ((tmp + (tmp >>> 4)) & 0x0f0f0f0f);
4    tmp = ((tmp + (tmp >>> 8)) & 0x00ff00ff);
5    return ((tmp + (tmp >>> 16)) & 0x0000ffff) % 63;
6}

17,每5位存储,使用减法

1public int hammingWeight(int n) {
2    n = n - ((n >>> 1) & 0xdef7bdef) - ((n >>> 2) & 0xce739ce7) - ((n >>> 3) & 0xc6318c63) - ((n >>> 4) & 0x02108421);
3    n = ((n + (n >>> 5)) & 0xc1f07c1f);
4    n = ((n + (n >>> 10) + (n >>> 20) + (n >>> 30)) & 63);
5    return n;
6}

18,每次消去最右边的1,可以参照第5种解法

1public static int hammingWeight(int num) {
2    int total = 0;
3    while (num != 0) {
4        num -= num & (-num);
5        total++;
6    }
7    return total;
8}

总结



这题如果一直写下去,再写10种也没问题,如果上面的代码你都能看懂,你也会有和我一样的想法。但解这题的最终思路还是没变,所以再写下去也没有太大价值。上面有些写法其实也很鸡肋,这里只是告诉大家这样写也是可以实现的,虽然可能你永远都不这样去写。

364,位1的个数系列(一)

385,位1的个数系列(二)

402,位1的个数系列(三)

361,交替位二进制数

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
剑指offer 11 二进制中1的个数
补数在进位加法和退位减法中的运用(修改)
补码到底是个什么东西
定义一递归函数,求给定正整数的二进制形式的位数。
C语言十进制转二进制代码实例
算法30(整数的二进制表示中1的个数)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服