【剑指offer】13二进制中1的个数

位运算

位运算是数字用二进制表示之后,对每一位上0或1的运算。

位运算一共有5种运算:

  • 异或
  • 左移
  • 右移
    在这里插入图片描述
    左移运算符m<<n表示把m左移n位。在左移的时候,最左边的n位将会被丢弃,同时在最右边补上n个0。

比如

00001010<<2=00101000
10001010<<3=01010000

右移运算符表示把m右移n位。在右移的时候,最右边的n位将会丢弃。但右移时处理最左边的情形要稍微复杂一些。
如果数字是无符号数值,则用0填补最左边的n位。
如果数字是有符号数值,则用数字的符号位填补最左边的n位。

也就是正数补1,负数补0。

00001010>>2=00000010
10001010>>3=11110001

面试题 二进制中1的个数

在这里插入图片描述

基本思路

  • 先判断整数最右边一位是不是1;
  • 把输入的整数右移1位。这时原本处于右边第二位的数被移到右边第一位,再判断是不是1.
  • 重复上面步骤,直到整个数变为0

现在的问题是如何判断最右边一位是不是1
只需要把整数和1做位与运算看结果是不是0。

因为1除了最右边一位是1外所有位都是0,与运算可以看出最后一位是0还是1。

C++
int NumberOfl(int n){
	int count=0;
	while(n){
		if(n&1)
			count++;
		n=n>>1;
	}
	return count;
}

这里需要注意的是虽然把整数右移一位和把整除除以2在数学上是等价的。但是除法的效率比移位运算效率要低得多,尽量用移位代替乘除法。

高级解法

下面介绍一种高级解法:整数中有几个1就只需要循环几次

思路解析

先分析把一个数减去1的情况。

如果一个数不等于0,那么该整数的二进制表示中至少有一个位是1.

先假设这个数的最右边一位是1,那么减去1的时候,最后一位变成0而其他所有位都保持不变。相当于最后一位进行了取反操作。

再假设这个数的最后一位是0.如果该整数的二进制表示中最右边的1位于第m位。那么减去1的时候,第m位变为0。而第m位之后的所有0都变成了1。第m位之前的所有位都保持不变。

在前面的两种情况中,我们发现把一个数减去1,都是把最右边的1变成0。如果它的右边还有0,如果它的右边还有0,则所有的0都变成1,而它左边的所有数都保持不变。

接下来我们把一个整数和它减去1的结果做位于运算,相当于把它最右边的1变成0

那么一个整数的二进制中表示中有几个1就会进行多少次这样的操作。

c++
int NumberOfl(int n){
	int count=0;
	while(n){
		count++;
		n=n&(n-1);
	}
	return count;
}

LeetCode

  1. 191. 位1的个数
  2. 338. 比特位计数 此题有高级解法 需要进一步研究
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值