剑指 Offer 15. 二进制中1的个数

剑指 Offer 15. 二进制中1的个数

剑指 Offer 15. 二进制中1的个数

请实现一个函数,输入一个整数(以二进制串形式),输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。

示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。

示例 2:
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1’。

示例 3:
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 ‘1’。

提示:
输入必须是长度为 32 的 二进制串 。


思路

该题是考察二进制运算相关知识点
俗话说会者不难,难者不会

带大家复习一下有关二进制的操作
二进制的操作有且仅有5种操作:
位与 &
位或 |
位异 ^
左移 <<
右移 >>

位运算符:& | ~ ^ << >>
按位与 & 1假即假
按位或 | 1真即真
按位非 ~ 真变假,假变真
左移<< 原数乘以进制^ 移动位数。举例:十进制239,左移2位,23900,即239 *10^2
右移>>原数除以进制^ 移动位数。举例:十进制138,右移3位,0.138,即138 *10^-3

需要注意的是:
左移运算符 m << n表示:把m左移n位,在左移n位的时候,最左边的n位将被丢弃,同时在最右边补上n个0
右移运算符 m >> n表示:把m右移n位,在右移n位的时候,最右边的n位将被丢弃。但是,右移时处理最左边的情形要稍微复杂一点。
如果数字是一个无符号数值,则用0填补最左边的n位;
如果数字是一个有符号数值,则用数字的符号位填补最左边的n位。
也就是说:
如果数字原来是一个正数,则右移之后在最左边补n个0;
如果数字原来是一个负数,则右移之后在最左边补n个1;

知道了二进制的相关操作,那么,如何判断某一位是否为1呢?
这就要使用位运算符中的:位与&了
如果某一位的值为0,则&1,该位为0;
如果某一位的值为1,则&1,该位为1。
从而可以判断出该位是0或者1

在此基础上,我们可以考虑让n每次左移一位,然后与1做比较

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int count = 0;
        while(n != 0){
            if((n & 1) != 0){
                count++;
            }
            n = n >>> 1;
        }
        return count;
    }
}
java中有三种移位运算符
<<      :     左移运算符,num << 1,相当于num乘以2
>>      :     右移运算符,num >> 1,相当于num除以2
>>>    :     无符号右移,忽略符号位,空位都以0补齐

以上解答,n = n >>> 1;可以
但是,修改为n = n >> 1;就不可以了
原因是,如果 n = n >> 1,那么如果n是负数,那么while(n != 0)一直成立,然后造成死循环

如果是C语言下,并没有>>>无符号右移操作,那么,在C语言下,又如何解决呢?

我们观察到,上面的写法是在移动n,每次将n右移一位
我们可以设置一个值flag,令flag = 1,每次将flag左移一位,做比较,效果与上面是一样的,而且,可以计算出负数情况下1的个数。

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int flag = 1;
        int count = 0;
        while(flag != 0){
            if((n & flag) != 0){
                count++;
            }
            flag = flag << 1;
        }
        return count;
    }
}

注意:
一开始写成了while(flag > 0)或者while(flag >= 0)都是不对的
如果n是负数,那么,flag最后也是负数
此时,如果使用>=0,则flag为负数,不会执行while循环,因此,n的最高位1没有被计算进去

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值