二进制中1的个数
二进制中1的个数
题目
实现一个函数,输入一个整数(以二进制串形式),输出该数二进制表示中 1 的个数。
例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
示例:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
利用位运算
作者:jyd
链接:https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/solution/mian-shi-ti-15-er-jin-zhi-zhong-1de-ge-shu-wei-yun/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
位运算
计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运算的运算
概览
- & :与,两个位都为1时,结果才为1
- | :或,两个位都为0时,结果才为0
- ^ :异或,两个位相同为0,相异为1
- ~ :取反,0变1,1变0
<<
:左移,各二进位全部左移若干位,高位丢弃,低位补0>>
:右移,各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)
方法一
与运算:&,两个位都为1时,结果才为1
设二进制数字n(把数字n看作无符号数)
-
若 n & 1 = 0 & 1= 0 ,则n二进制 最右一位为 0
-
若 n & 1 = 1 & 1= 1 ,则n二进制 最右一位为 1
根据以上特点,考虑以下循环判断 :
- 判断n最右一位是否为1,根据结果计数。
- 将n右移一位
- res += n & 1,若 n & 1 = 1,则统计数 res 加一。
- n >>= 1,将二进制数字n无符号右移一位(Java 中无符号右移为 ">>>>>>")
- 返回统计数量 res
时间复杂度 O(log2 n)
方法二
- (n−1):二进制数字n最右边的1变成0,此1右边的0都变成1 。
- n & (n - 1):二进制数字n最右边的1变成0,其余不变
过程:
- 初始化数量统计变量 res
- 循环消去最右边的1:当n = 0时跳出。
- res += 1:统计变量加1;
- n &= n - 1:消去数字n最右边的1 。
返回统计数量 res
代码实现
方法一
/*
* n是传入进来的二进制数
* n != 0 是循环条件
* res += n & 1
* 若此位上的数字为0,0 & 1 = 0,res不变;
* 若此位上的数字为1,1 & 1 = 1,res加1;
* n >>>= 1,将数字n无符号右移
*
*/
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int res = 0;
while(n != 0){
res += n & 1;
n >>>= 1;
}
return res;
}
}
方法二
/*
* n是传入进来的二进制数
* n != 0 是循环条件
* n & (n - 1):数字n最右边的1变成0,其余不变
*
*/
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int res = 0;
while(n != 0){
res ++;
n &= (n - 1);
}
return res;
}
}