JZ11 二进制中1的个数

题目描述

输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。

示例1

  • 输入:10
  • 返回值:2

题解

  • 知识点:二进制,位运算
  • 难度:一星

方法一:暴力方法

分析:题目给一个有符号的整数int,求整数转化成二进制数后,统计1的个数。
直接根据题目的描述来提出方法一。有2个问题:
问题1: 如何从十进制数转化到二进制数?
问题2:转化为二进制数后,如果判断有1的个数?
方法1:除2取模法。

方法 二:技巧法

思路

利用一个结论:一个二进制数n减1后与原二进制数进行&运算( 即n&(n-1) )会消去最右边的1。即整数n,进行n&(n-1)运算,会把二进制表示中最右边的1变为0。

结论验证
  • 101 & 100
    假设二进制数101进行减1运算,刚好最右边是1,则得到100,此时用100跟101做&运算,得到的是100,故消去了101左右边的1。
  • 100 & 99
    二进制100减1的运算过程如下:
    (1)最右边的0向右数第二位借1得:2-1=1,
    (2)右数第二位还是0,却要借给最右边那位1,所以它也得向高位借。
    (3)这样右数第三位的1借给它1之后变成0,右数第二位借1得:2-1=1。
    (4)所以得到新数为011。

总结:

  • 如果最右边刚好是1(如101),进行减1运算就不用向高位借,直接得0,高位则保持原样不变(得100)。
  • 再把减1后得到的数与原数&运算(即101&100=100),可知高位都不变那就是消去最右边的1。
  • 如果最右边是0(如100),进行减1运算,则需要像高位借,而最终会导致最近的高位1因为被借走1而变0,而比它高的高位保持原样不变(得011),再跟原来的数进行&运算(即100&011=000);
  • 所以由以上两点可知二进制数每次减1后与原数进行&运算会消去最右边的1。
代码一:C#
		public int NumberOf1(int n)
        {
            var num = 0;
            while (n != 0)
            {
                num++; // 如果一个整数不为0,那么这个整数至少有一位是1。
                n = (n - 1) & n;
            }

            return num;
        }

时间复杂度:O(n) n为val中1的个数
空间复杂度:O(1)

方法二:

public class Solution 
{
    public int NumberOf1(int n) 
    {
        int count = 0;
        int i = 32;
        
        while( i > 0)
        {
            count = count + (n & 1); //每次判断最低位是否为1
            n = n >> 1;
            i--;
        }
        return count;
    }
}

位运算中<<、>>、>>>的区别:

  1. << 表示左移,不分正负数,低位补0;
  2. >> 表示右移,若该数为正,高位补0;若该数为负,高位补1;
  3. >>> 表示无符号右移,也称逻辑右移,不分正负数,高位补0;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值