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

想了解更多数据结构以及算法题,可以关注微信公众号“数据结构和算法”,每天一题为你精彩解答。也可以扫描下面的二维码关注
在这里插入图片描述

我们知道在java语言中一个int类型有32个0或1组成。我们要计算有多少个1,这里主要以int型数据为例来分析。比如15在二进制中表示的是1111,有4个1,所以返回4。再比如16在二进制中表示的是10000,只有一个1,所以返回1。这题解法比较多,我们将会逐个分析。

一,通过移动数字计算

首先想到的是把要求的数字不停的往右移,然后再和1进行与运算,我们就以13为例画个图来分析下

在这里插入图片描述
看明白了上面的分析,代码就很容易多了,我们来看下代码

public int bitCount(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if (((n >>> i) & 1) == 1) {
            count++;
        }
    }
    return count;
}

上面的分析中我们看到,如果一个数往右移了几步之后结果为0了,就没必要在计算了,所以代码我们还可以在优化一点

public int bitCount(int n) {
    int count = 0;
    while (n != 0) {
        count += n & 1;
        n = n >>> 1;
    }
    return count;
}

二,通过移动1来计算

上面我们使用的是把一个数字不断的往右移动,其实我们还可以保持原数字不变,用1和他进行与运算,然后通过移动1的位置来计算,这里我们判断的标准不是等于1,而是不等于0。我们还以13为例来画个图分析一下

在这里插入图片描述
这次我们移动的是1,我们来看一下代码

public int bitCount(int n) {
    int count = 0;
    for (int i = 0; i < 32; i++) {
        if ((n & (1 << i)) != 0) {
            count++;
        }
    }
    return count;
}

当然我们还可以通过运算的结果是否是1来判断也是可以的,我们只需要把往左移的1和n运算完之后再往右移即可,我们来看下代码

public int bitCount(int i) {
    int count = 0;
    for (int j = 0; j < 32; j++) {
        if ((i & (1 << j)) >>> j == 1)
            count++;
    }
    return count;
}

三,不通过移位计算

前面两种方式要么是移动原数字,要么是移动1,这次我们不移动任何数字来计算。在位运算中有这样一个操作,就是n&(n-1)可以把n最右边的1给消掉。举个例子,当n=12的时候,我们来画个图看一下
在这里插入图片描述
明白了这个知识点,代码就很容易写了,我们通过循环计算,不断的把n右边的1给一个个消掉,直到n等于0为止

public int bitCount(int n) {
    int count = 0;
    while (n != 0) {
        n &= n - 1;
        count++;
    }
    return count;
}

我们还可以把它给为递归的写法,直接一行代码搞定

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

四,查表

我们还可以通过查表来计算,我们先要把0到15转化为二进制,记录下每个数字包含1的个数再构成一张表,然后再把数字n每4位进行一次计算,图就不画了,代码中有注释,我们来看下代码

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

这题我感觉还是比较经典的,因为他的解法非常多,上面的几种要么使用循环,要么使用递归,要么是查表,其实我们还可以上面几种方式都不使用,也可以计算1的个数,这个后面会再讲。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据结构和算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值