【剑指Offer】个人学习笔记_15_二进制中1的个数

刷题日期:18:5215 星期三2021年3月24日

个人刷题记录,代码收集,来源皆为leetcode

经过多方讨论和请教,现在打算往Java方向发力

主要答题语言为Java

题目:

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

难度简单98

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

示例 1:

输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'

示例 2:

输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'

示例 3:

输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'

提示:

  • 输入必须是长度为 32二进制串
题目分析

根据提示,输入长度为32位的二进制串,看题目里输入的是int型

最简单的方法肯定是直接转换成char类型一个一个数。

这道题涉及到位运算,可能在程序中也需要一些位运算的符号。

与、或、异或、左右移

初始解答:

直接判断最右边然后位移

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

if语句后面报错了,不知道为啥,java也支持位运算

参考了方法一,发现while循环的条件和if 的条件都不对,因为n不是布尔值,所以不能直接拿来当判断条件。

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

修改发现老是超出时间限制,继续修改if中的位移操作。

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

把唯一操作移出就好了,这样按照题目的输入,位移操作被执行了32次,不管是0还是1都会判断然后位移。

这里需要注意,位移操作>>>和>>的区别,前者按位右移补零操作符,具体区别附在了最后面。

执行结果:通过

显示详情

执行用时:1 ms, 在所有 Java 提交中击败了96.85%的用户

内存消耗:35.6 MB, 在所有 Java 提交中击败了9.17%的用户

根据书里“能给面试官带来惊喜的解法”,把一个整数减去1,再与原数做与运算,会把该整数最右边的1变成0,依此进行尝试:

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

没有问题,就是需要记住性质。

执行结果: 通过

显示详情

执行用时:1 ms, 在所有 Java 提交中击败了96.85%的用户

内存消耗:35.6 MB, 在所有 Java 提交中击败了17.13%的用户

学习他人:

方法一:

炉石鲍勃L1 (编辑过)2021-02-28

无符号右移就可以了

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

方法二

java.lang包的Integer类的bitCount()方法以整数值的二进制补码表示形式返回one-bits的数量计数。有时将此功能称为人口计数。

用法:

public static int bitCount(int n)
参数:
n: the value whose bits are to be counted
返回:
This method returns the count of the number of one-bits in the two's complement 
binary representation of an int value.

月亮很亮L1 2020-02-25

java居然有这个方法

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        return Integer.bitCount(n);
    }
}

方法三:

Joker 2020-07-03

python一行

 return bin(n).count('1')

Java位运算

下表列出了位运算符的基本运算,假设整数变量 A 的值为 60 和变量 B 的值为 13:

原网址

操作符描述例子
如果相对应位都是1,则结果为1,否则为0(A&B),得到12,即0000 1100
|如果相对应位都是 0,则结果为 0,否则为 1(A | B)得到61,即 0011 1101
^如果相对应位值相同,则结果为0,否则为1(A ^ B)得到49,即 0011 0001
按位取反运算符翻转操作数的每一位,即0变成1,1变成0。(〜A)得到-61,即1100 0011
<<按位左移运算符。左操作数按位左移右操作数指定的位数。A << 2得到240,即 1111 0000
>>按位右移运算符。左操作数按位右移右操作数指定的位数。A >> 2得到15即 1111
>>>按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。A>>>2得到15即0000 1111

总结

以上就是本题的内容和学习过程了,这道题比较简单,理解位运算的思路即可,没啥太多好说的。

欢迎讨论,共同进步。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值