【剑指Offer记录】15_二进制中1的个数

Part1. 我的思路和代码

依次判断每一位是否是1。将二进制表示与0x1进行与运算,结果为1、0分别说明最低位为1、0,然后将二进制右移1位,重复同样的过程,一共循环32次。

int NumberOf1(int n) {
    int ans = 0;

    for(int i=0; i<32; i++){
        if(n&1){
            ++ans;
        }
        n = n >> 1;
    }

    return ans;
}

特别记录:如果不进行32次循环,而是通过判断n是否为0的方式控制循环结束,需要注意如果n原本是负数,那么进行右移操作后,最高位会用1补充,会造成死循环。

Part2. 其他做法

1. 不同的循环方式

不改变原整数的二进制值,而是从低位到高位依次,通过将0x1左移的方式提取每一位的值。

int NumberOf1(int n) {
    int ans = 0;
    int temp = 1;

    while(temp){
        if(n&temp){
            ++ans;
        }
        temp = temp << 1;
    }

    return ans;
}

2. 有几个1就循环几次的做法

该做法的根据是:将一个数减去1,将结果和原整数进行与运算,会把二进制表示中最右边的1变为0。于是二进制中有几个1,就可以进行几次这样的操作。

int NumberOf1(int n) {
    int ans = 0;

    while(n){
        n = n & (n-1);
        ++ans;
    }

    return ans;
}

Part3. 相关题目

题目1

判断一个整数是不是2的整数次方。

如果是2的整数次方,那么二进制中1的个数为1。可以用循环来计算1的个数,而使用“有几个1就循环几次的做法”是效率更高的选择。

题目2

两个整数m、n,求m中需要改变多少个二进制位才能将m变为n。

直接对比m、n的二进制中1的个数的差值是不可行的,因为1的个数相同时,二进制也可以不同,如1100和0011,所以需要先得到m和n哪些位是不一样的。根据异或运算的规律,如果对应的位相同,运算后结果为0,如果对应的位不同,结果为1,于是先将m和n进行异或运算得到r,判断r中1的个数即为所求。

Part4. 心得体会

  • 我自己是想不到“有几个1就循环几次”的做法的,做此题目也是属于一种知识的积累。
  • 原本打算不记录这道题的,但从这道题新学到了一些内容,于是也记录了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值