剑指Offer15.二进制中1的个数

  • 剑指Offer15.二进制中1的个数

  • 题目:
    一个uint32_t数n,返回n在计算机中的二进制表示中1的个数;

  • 思路:
    1.循环取二进制的最低位,并右移;O(logn):n每次除2,logn次循环后为0,(实际上更确切的说,logn指n的二进制表示中最高位1所在的位数(例如log16 = 4)),O(1)
    无符号数在计算机中,无论左移还是右移都是逻辑移位,即补0;
    n & 1:取到n的二进制表示的最低位
    n >> 1:逻辑右移,在左边补0
    循环取n的二进制表示的最低位,直至n==0;

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int res = 0;//统计1的个数
        while (n) {
            res += n & 1, n >>= 1;//n&1得到n的二进制表示的最低位;n>>1
        }
        return res;
    }
};

2.(借鉴大佬的做法)巧用n & (n -1):O(m):m表示n的二进制中1的个数,O(1)
n & (n - 1)可以把n的最低位1变成0;
在这里插入图片描述

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int res = 0;//统计1的个数
        while (n) {
            n &= (n - 1);//每次把n的最低位的1变成0
            ++res;
        }
        return res;
    }
};

附注:若本题给的n时有符号整数,难度增加:
3.在C++中如果我们右移一个负整数,系统会自动在最高位补1,这样会导致 n 永远不为0,就死循环了;
解决办法是把 int强制转化成unsigned int,这样 n 的二进制表示不会发生改变,但在右移时系统会自动在最高位补0,最终n会变成0退出循环;

class Solution {
public:
    int NumberOf1(int n) {
        unsigned int un = n;//核心所在,转换位unsigned int后,就跟前面这道题一样了,用1和2均可
        int res = 0;
        while (un) {
            res += (un & 1);
            un >>= 1;
        }
        return res;
    }
};
  • 总结:
    1.同一类型的unsigned和signed的二进制表示是不变的,变的是计算机的解释方法不同:实际就是最高位的权值一正一负,例如把有符号数-1转换成unsigned int后,二者的二进制表示都是11111111 11111111 11111111 11111111,但最高位1的权重一个是2 ^ 31,一个是 - 2 ^ 31;
    2.n & 1可以得到n的二进制的最低位,配合右移使用;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值