最强解析面试题:二进制中 1 的个数「建议收藏!炸!」

Posted 魏小言

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最强解析面试题:二进制中 1 的个数「建议收藏!炸!」相关的知识,希望对你有一定的参考价值。


最强解析面试题:二进制中 1 的个数「建议收藏!」

文章讲解 “ 二进制中 1 的个数 ” 经典面试题,包含思路及源码,及解惑!

题目

输入一个整数,输出该数二进制表示中 1 的个数。其中负数用补码表示。
数据范围:2^ 32

示例1

输入:
3
返回值:
2

思路

运用位运算

依次判断二进制数末尾是否为 1 ,时间复杂度是二进制位数。
位运算 (>>、&):二进制数与 1 做 & 运算,每次右移一位,直至数值为 0。

例子: 2
0010 & 0001 = 0000 ;
2 >> 1 = 0001;
0001 & 0001 = 0001;
0001 >> 1 = 0;
& 运算次数为 2 ,结果为 1 的为一次,故 2 二进制中 1 的个数为 1。

代码
package main


/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 * 
 * @param n int整型 
 * @return int整型
*/
func NumberOf1( n int ) int {
    // write code here
    var m int32 = int32(n)
    var res int
    var flag int32 = 1
    for flag != 0{
        if m&flag != 0{
            res++
        }
        flag<<=1  
    }
    return res
}
运行结果

运行时间:4ms
超过90.00% 用Go提交的代码
占用内存:1347KB
超过36.86%用Go提交的代码

运用 n 与 n-1 二进制之间的数据关系

n 与 n-1、n+1、之间相差 1 ,二进制表现为有效位 1 之后取反。n & (n-1)可消掉 n 最地位有效 1 ,时间复杂度为二进制数中 1 的个数。

例子:2
2 & 1 = 0010 & 0001 = 0000 「把 0010 最低位 1 消除」
& 运算次数为 1,故 2 二进制中 1 的个数为 1。

代码
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 * 
 * @param n int整型 
 * @return int整型
*/
func NumberOf1( n int ) int {
    // write code here
    var m int32 = int32(n)
    var res int
    for m !=0{
        m&=(m-1)
        res++
    }
    return res
}
运行结果

运行时间:2ms
超过64.87% 用Go提交的代码
占用内存:860KB
超过62.53%用Go提交的代码

Q&A

负数问题

有同学会疑问:负数怎么办?负数使用补码和正数不一致啊,是不是对负数需要进行额外的处理?

答案是,不用。正数存储其实也是补码,只不过和自身一样而已。

位移运算

注意:Goland 中无 “无符号左右移”,Java 等其它语言支持
若用 Java 实现,则思路一中可直接 无符号右移 N 即可,无需像 Go ,转弯思路去右移 Flag。

类型问题

注意:Goland 中 int 类型,有多种 int8\\int16\\int32….,单独只写 int,会自动根据系统默认,故这里需要根据题目区间特写 int32

边界问题

题目中已经指出为 int32 类型,需要考虑越界问题。

方案一中的
if m&flag != 0
不能调整为 m&flag == 1 或者 res+=m&flag,因为存在正负符号位,负数的符号位要算进去。

附录

诡异的问题背后,往往是低级的错误!

以上是关于最强解析面试题:二进制中 1 的个数「建议收藏!炸!」的主要内容,如果未能解决你的问题,请参考以下文章

最强解析面试题:在无序数组中取最大的K个数「建议收藏!」

最强解析面试题:在无序数组中取最大的K个数「建议收藏!」

最强解析面试题:在无序数组中取最大的K个数「建议收藏!」

最强解析面试题:替换空格「建议收藏!」

最强解析面试题:替换空格「建议收藏!」

最强解析面试题:从尾到头打印链表「建议收藏!」