剑指offer 学习笔记 位运算
位运算是把数字用二进制表示后,对每一位上的0或者1的运算。
面试题15:二进制中1的个数。请实现一个函数,输入一个整数,输出该数二进制表示(即补码表示)中1的个数。例如,把9表示成二进制是1001,有2位是1。因此,如果输入9,则函数输出2。
很快我们得到一个思路,先判断该数二进制表示中右边一位是不是1,接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断是不是1,重复以上步骤直到该数变为0。判断最右边一位是否是1,只需要把要判断的数和1相与,结果为1则表示最右边一位为1,否则为0。把整数右移一位和把整数除以2是等价的,但移位运算的效率比除法高得多,用到除法的地方最好用移位运算代替:
#include <iostream>
using namespace std;
int NumberOf1(int num) {
int count = 0;
while (num) {
if (num & 1) {
++count;
}
num >>= 1;
}
return count;
}
int main() {
cout << NumberOf1(9) << endl;
return 0;
}
但这种解法有一个问题,当输入的数字为负数时,大多数编译器在右移时左边会复制符号位,那么最终循环到整个数的二进制位全为1,陷入死循环。
为了避免死循环,我们可以不右移输入的数字n,首先把n与1做与运算,判断n的最低位是不是1,接着把1左移一位得到2,再与n与运算判断次低位是不是1,重复以上过程,直到1变为0:
#include <iostream>
using namespace std;
int NumberOf1(int num) {
int count = 0;
int flag = 1;
while (flag) {
if (num & flag) {
++count;
}
flag <<= 1;
}
return count;
}
int main() {
cout << NumberOf1(-1) << endl; // 由于-1的补码为32个1,输出32
return 0;
}
这个解法中,循环的次数等于二进制的位数,32位整数循环32次,接下来是一种有几个1循环几次的解法。
我们先分析将一个数减去1的情况。如果一个整数不等于0,那么该整数的二进制表示中至少有一位是1,先假设这个数的最右边的值为1,那么减去1时,最后一位变成0,而其他所有位都保持不变,相当于最后一位做了取反操作,由1变为了0。接下来假设最后一位不是1而是0时的情况,如果该数的二进制表示中最右边的1位于第m位,那么减去1时,第m位由1变为0,m位之后的所有0变为1,m位之前的所有位都保持不变。我们可以发现,当把一个数减去1的结果与这个数做与运算,会把这个数的最右边的1变为0,如1100,减去1之后变为1011,相与结果为1000。那么这个数中有几个1,重复几次此操作即可:
#include <iostream>
using namespace std;
int NumberOf1(int num) {
int count = 0;
while (num) {
++count;
num &= (num - 1);
}
return count;
}
int main() {
cout << NumberOf1(-1) << endl;
return 0;
}
相关题目:
1.一条语句判断一个整数是否为2的整次方,如果是,那么它的二进制表示中只有一个1,根据前面分析,把这个整数减去1之后与它自己相与结果为0就是2的整数次方。
2.输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。比如10的二进制位为1010,13的二进制位为1101,则需要改变三个二进制位。求解这个问题可分为两步,第一步求出这两个值的异或,最后找异或结果中有几个1。
把一个整数减去1之后结果与原来的整数做位与运算,得到的结果相当于把最右边的1变成0。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2019-02-18 JAVA数据类型