一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
题目:编写一个函数,其输入是一个无符号整数,要求返回二进制表达中数字位数为1的个数。
输入:n = 11 (控制台输入 00000000000000000000000000001011) 输出:3 解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
但Java中没有无符号数,例如对于 11111111111111111111111111111101,其输入为-3。
输入:n = 4294967293 (控制台输入 11111111111111111111111111111101,部分语言中 n = -3) 输出:31 解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。
解题思路
java 中没有无符号数,也即代表我们无法直接使用除2取余法。本题看似简单,实际上考察的是对计算机底层原理的相关内容的考察,例如移位运算以及与运算等。
首先介绍移位运算,给定一个二进制数,例如0001,十进制中这个数代表1,那如果想将这个数乘2,只需要将二进制数中的最后一个1左移,依次类推,可得到2^n的结果,右移同理,相当于除法。
再说& ,只有当左右两边都为1的时候,其值才为1。那么就可以用这个性质来判断指定第几位是否为1,因为只要其它位都是0,指定为是1则可以得到值是否为0。我们也可以用这个性质来消除一个二进制数的最后一个1,即使用n & (n-1)。
根据上面两个思路,可以很简单得到如下代码:
public static int hammingWeight3(int n) {
int count = 0;
for(int i=0;i<32;i++){
if((n & (1<<i))!=0) count++;
}
return count;
}
上面的方法是按位判断每位是否为1,因为限定了数的长度为32位。时间复杂度为。另一个思路是直接一步步消除原始数的1,代码如下:
public int hammingWeight2(int n) {
int count = 0;
while(n!=0){
count++;
n = n & (n-1);
}
return count;
}
通过将数的末尾1一个个消除,从而得到最终的结果。时间复杂度为。