剑指Offer算法笔记(Java)二进制中1的个数

24 篇文章 0 订阅
12 篇文章 0 订阅

12.二进制中1的个数

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

数据范围:- 2^{31} <= n <= 2^{31}-1−2 31<=n<=2 31 −1
即范围为:-2147483648<= n <= 2147483647−2147483648<=n<=2147483647
示例1
输入:
10

返回值:
2

说明:
十进制中10的32位二进制表示为0000 0000 0000 0000 0000 0000 0000 1010,其中有两个1。
示例2
输入:
-1

返回值:
32

说明:
负数使用补码表示 ,-1的32位二进制表示为1111 1111 1111 1111 1111 1111 1111 1111,其中32个1

方法一:循环按位比较法

思路:

我们可以检查该数字的二进制每一位是否为1,如果遍历二进制每一位呢?可以考虑移位运算,每次移动一位就可以。至于怎么统计到1呢?我们都只知道数字1与数字相位与运算,其实只是最后一位为1就是1,最后一位为0就是0,这样我们只需要将数字1移位运算,就可以遍历二进制的每一位,再去做位与运算,结果为1的就是二进制中为1的。

具体做法:

step 1:遍历二进制的32位,通过移位0-31次实现。
step 2:将移位后的1与数字进行位与运算,结果为1就记录一次。

Java实现代码:

import java.util.*;
public class Solution {
    public int NumberOf1(int n) {
        int res = 0;
        for(int i = 0;i<32;i++){
            
            if((n &(1<<i))!=0){
                
                res++;
                
            }
            
        }
        return res;

    }
}

复杂度分析:

时间复杂度:O(k),k为int型的32位,一次遍历
空间复杂度:O(1),常数级变量,没有额外辅助空间

方法二:位运算优化法

思路:

有一个性质:n&(n−1),会将n的二进制中最低位由1变成0

我们可以不断让当前的 n与 n−1做位与运算,直到 n的二进制全部变为 0 停止。因为每次运算会使得 n 的最低位的 1 被翻转成0,因此运算次数就等于 n 的二进制位中 1 的个数,由此统计1的个数。

具体做法:

step 1:使用循环检查n是否为0.
step 2:不为0就与n−1做位与运算,去掉二进制最后一位的1,并统计次数。

Java实现代码:

public class Solution {
    public int NumberOf1(int n) {
        int res = 0;
        //当n为0时停止比较
        while(n != 0){  
            n &= n - 1;
            res++;
        }
        return res;
    }
}

复杂度分析:

时间复杂度:O(log2n),n为数字的大小,循环次数等于nnn的二进制位中1的个数,最坏情况下n的二进制位全部为1,也即开一个2的log运算
空间复杂度:O(1),常数级变量,没有额外辅助空间

方法三:暴力法

直接利用Integer提供的API将数字转化为二进制表示的字符串,然后就可以直接通过charAt()记录1的个数,或者使用replace()把0给替换掉再返回字符串长度。

public class Solution {
    // replace替换
    public int NumberOf1(int n) {
        return Integer.toBinaryString(n).replace("0","").length();
    }

    // 遍历字符串记录
    public int NumberOf1(int n) {
        String str = Integer.toBinaryString(n);
        int length = str.length();
        int count = 0;
        for (int i=0; i<length; i++) {
            if (str.charAt(i) == '1') {
                count++;
            }
        }
        return count;
    }
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十三幺Shisanyao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值