news 2026/4/23 17:47:08

【算法题】位运算

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【算法题】位运算

位运算是利用二进制位特性解决问题的高效算法,核心通过「与(&)、或(|)、异或(^)、移位(<< / >>)」等基础操作,将时间/空间复杂度优化到极致(通常为O(n)O(n)O(n)时间、O(1)O(1)O(1)空间)。
它的应用场景覆盖“位计数”“找唯一数”“数值运算”“状态压缩”等核心问题,是算法面试中高频且易掌握的考点。本文将通过10道经典题目,拆解位运算在不同场景下的解题逻辑与代码实现。

一、汉明重量(统计二进制中1的个数)

题目描述:
输入一个无符号整数(二进制串形式),返回其二进制表达式中数字位数为1的个数(汉明重量)。

示例

  • 输入:n = 00000000000000000000000000001011,输出:3
  • 输入:n = 11111111111111111111111111111101,输出:31

解题思路:
利用n & (n - 1)的核心特性:该操作会消去n二进制中最右边的1。循环执行该操作直到n为0,统计循环次数即为1的个数。

完整代码:

classSolution{public:inthammingWeight(intn){intcnt=0;while(n){n&=(n-1);cnt++;}returncnt;}};

复杂度分析:

  • 时间复杂度:O(k)O(k)O(k)k是二进制中1的个数(最坏O(32)O(32)O(32),常数级)。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

二、比特位计数

题目描述:
给定整数n,对0 ≤ i ≤ n的每个i,计算其二进制中1的个数,返回长度为n+1的结果数组。

示例

  • 输入:n = 2,输出:[0,1,1]
  • 输入:n = 5,输出:[0,1,1,2,1,2]

解题思路:
复用“汉明重量”的核心逻辑:遍历0~n的每个数,逐个统计二进制中1的个数,存入结果数组。

完整代码:

classSolution{public:vector<int>countBits(intn){vector<int>ret;intcnt=0;for(inti=0;i<=n;i++){inttmp=i;while(tmp){tmp&=(tmp-1);cnt++;}ret.push_back(cnt);cnt=0;}returnret;}};

复杂度分析:

  • 时间复杂度:O(n×k)O(n×k)O(n×k)k是单个数字二进制中1的个数(最坏O(32n)O(32n)O(32n),仍为线性级)。
  • 空间复杂度:O(1)O(1)O(1),结果数组为必要输出,不计入额外空间。

三、汉明距离

题目描述:
两个整数的汉明距离是其二进制位不同的位置数目。给定xy,返回它们的汉明距离。

示例

  • 输入:x = 1, y = 4,输出:2(1:0001,4:0100,不同位有2个)

解题思路:

  1. 异或操作x ^ y:结果中1的位置对应两个数二进制不同的位置,0对应相同位置。
  2. 统计异或结果中1的个数(复用汉明重量逻辑),即为汉明距离。

完整代码:

classSolution{public:inthammingDistance(intx,inty){intn=x^y;intret=0;while(n!=0){n&=n-1;ret++;}returnret;}};

复杂度分析:

  • 时间复杂度:O(k)O(k)O(k)k是异或结果中1的个数(常数级)。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

四、只出现一次的数字(其余出现两次)

题目描述:
给定非空整数数组,除某个元素只出现一次外,其余元素均出现两次。找出该元素(要求线性时间、不使用额外空间)。

示例

  • 输入:nums = [2,2,1],输出:1
  • 输入:nums = [4,1,2,1,2],输出:4

解题思路:
利用异或的核心特性:

  • a ^ a = 0(相同数异或抵消);
  • a ^ 0 = a(与0异或保留自身);
  • 异或满足交换律/结合律。
    遍历数组,所有数异或的结果即为只出现一次的数。

完整代码:

classSolution{public:intsingleNumber(vector<int>&nums){intret=0;for(autox:nums){ret^=x;}returnret;}};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),遍历数组一次。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

五、只出现一次的数字(其余出现三次)

题目描述:
给定整数数组,除某个元素只出现一次外,其余元素均出现三次。找出该元素(要求O(n)O(n)O(n)时间、O(1)O(1)O(1)空间)。

示例

  • 输入:nums = [2,2,3,2],输出:3
  • 输入:nums = [0,1,0,1,0,1,99],输出:99

解题思路:
二进制位统计

  1. 遍历每一位(0~31位,覆盖int所有位):
    • 统计数组中所有数在该位上1的总个数sum
    • sum % 3 = 1,说明唯一数在该位上是1(其余数出现三次,该位1的个数是3的倍数,抵消后剩余1);
  2. 逐位构建结果:将为1的位通过ret |= 1 << i写入结果。

完整代码:

classSolution{public:intsingleNumber(vector<int>&nums){intret=0;for(inti=0;i<32;i++){intsum=0;for(autox:nums)if(((x>>i)&1)==1)sum++;sum%=3;if(sum==1)ret|=1<<i;}returnret;}};

复杂度分析:

  • 时间复杂度:O(32n)O(32n)O(32n),遍历32位,每位遍历数组一次(仍为线性级O(n)O(n)O(n))。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

六、只出现一次的数字(两个唯一数)

题目描述:
给定整数数组,恰好两个元素只出现一次,其余元素均出现两次。找出这两个元素(要求O(n)O(n)O(n)时间、O(1)O(1)O(1)空间)。

示例

  • 输入:nums = [1,2,1,3,2,5],输出:[3,5]

解题思路:

  1. 全体异或:得到两个唯一数的异或和xor_sum(其余数出现两次,异或抵消)。
  2. 找最低位1:lowbit = xor_sum & (-xor_sum),该位表示两个唯一数在该位上二进制不同。
  3. 分组异或:按lowbit将数组分为两组(该位为0/1),每组内只有一个唯一数,其余数出现两次,分别异或得到结果。
    ⚠️ 注意:==优先级高于&,判断时需加括号。

完整代码:

classSolution{public:vector<int>singleNumber(vector<int>&nums){unsignedintxor_sum=0;for(autoc:nums){xor_sum^=c;}intlowbit=xor_sum&(-xor_sum);vector<int>ret(2);for(autoc:nums){if((lowbit&c)==0)// == 优先级高于 &,必须加括号ret[0]^=c;elseret[1]^=c;}returnret;}};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),两次遍历数组。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

七、判定字符是否唯一

题目描述:
实现算法判断字符串astr的所有字符是否唯一(进阶:不使用额外数据结构)。

示例

  • 输入:astr = "leetcode",输出:false
  • 输入:astr = "abc",输出:true

解题思路:
状态压缩:用一个int(32位)的每一位表示对应字母(a-z)是否出现过:

  1. 若字符串长度>26,直接返回false(a-z仅26个字母)。
  2. 遍历字符,计算偏移量i = ch - 'a'
    • 检查(bitMap >> i) & 1,若为1说明字符重复;
    • 否则将bitMap的第i位设为1(bitMap |= (1 << i))。

完整代码:

classSolution{public:boolisUnique(string astr){if(astr.size()>26)returnfalse;intbitMap=0;for(autoch:astr){inti=ch-'a';if((bitMap>>i)&1==1)returnfalse;bitMap|=(1<<i);}returntrue;}};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),遍历字符串一次(n≤26,常数级)。
  • 空间复杂度:O(1)O(1)O(1),仅用一个int存储状态。

八、缺失的数字

题目描述:
给定包含[0, n]n个数的数组nums,找出[0, n]范围内未出现的数。

示例

  • 输入:nums = [3,0,1],输出:2
  • 输入:nums = [0,1],输出:2

解题思路:
复用异或特性:

  1. 将数组所有数异或,得到中间结果。
  2. 再将中间结果异或0~n的所有数,最终结果即为缺失的数(出现两次的数抵消,缺失数仅异或一次)。

完整代码:

classSolution{public:intmissingNumber(vector<int>&nums){intret=0;for(autoch:nums)ret^=ch;for(inti=0;i<=nums.size();i++)ret^=i;returnret;}};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),两次遍历(数组+0~n)。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

九、两整数之和

题目描述:
不使用+-运算符,计算并返回两个整数ab的和。

示例

  • 输入:a = 1, b = 2,输出:3
  • 输入:a = -2, b = 3,输出:1

解题思路:
用位运算模拟加法:

  1. 异或a ^ b:得到两数相加无进位的结果。
  2. 与运算后左移1位(a & b) << 1:得到相加的进位值
  3. 循环:将无进位结果作为新的a,进位作为新的b,直到进位为0,此时a即为和。

完整代码:

classSolution{public:intgetSum(inta,intb){while(b){intx=a^b;intcarry=(a&b)<<1;a=x;b=carry;}returna;}};

复杂度分析:

  • 时间复杂度:O(k)O(k)O(k)k是二进制位数(常数级)。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

十、丢失的两个数字

题目描述:
给定数组包含1~N的整数(缺两个数),在O(n)O(n)O(n)时间、O(1)O(1)O(1)空间内找出这两个数。

示例

  • 输入:nums = [1],输出:[2,3]
  • 输入:nums = [2,3],输出:[1,4]

解题思路:
结合“两个唯一数”和“缺失数字”的逻辑:

  1. 全体异或:数组所有数异或1~n+2n是数组长度),得到两个缺失数的异或和ret
  2. 找最低位1:lowbit = ret & (-ret),按该位分组。
  3. 分组异或:每组内分别异或数组元素和1~n+2的数,得到两个缺失数。

完整代码:

classSolution{public:vector<int>missingTwo(vector<int>&nums){intret=0;for(autox:nums)ret^=x;for(inti=1;i<=nums.size()+2;i++)ret^=i;intlowbit=ret&(-ret);vector<int>ans(2);for(autox:nums)if((lowbit&x)==0)ans[0]^=x;elseans[1]^=x;for(inti=1;i<=nums.size()+2;i++)if((lowbit&i)==0)ans[0]^=i;elseans[1]^=i;returnans;}};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),多次遍历数组/数字范围,均为线性级。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:13:11

突破4步精通JPEXS:Flash反编译的实战解决方案

突破4步精通JPEXS&#xff1a;Flash反编译的实战解决方案 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler 你是否曾经面对损坏的SWF文件束手无策&#xff1f;或者需要从旧版Flash项目中提…

作者头像 李华
网站建设 2026/4/23 12:36:46

ComfyUI工具节点终极指南:解锁高效AI图像处理新境界

ComfyUI工具节点终极指南&#xff1a;解锁高效AI图像处理新境界 【免费下载链接】comfyui-tooling-nodes 项目地址: https://gitcode.com/gh_mirrors/co/comfyui-tooling-nodes 你是否曾为AI图像处理中的复杂流程而烦恼&#xff1f;传统方法需要反复上传下载文件&#…

作者头像 李华
网站建设 2026/4/22 21:08:24

ImageGlass 开源图像查看器:高效图像浏览终极指南

ImageGlass 开源图像查看器&#xff1a;高效图像浏览终极指南 【免费下载链接】ImageGlass &#x1f3de; A lightweight, versatile image viewer 项目地址: https://gitcode.com/gh_mirrors/im/ImageGlass ImageGlass 是一款开源图像查看器&#xff0c;以其轻量级设计…

作者头像 李华
网站建设 2026/4/22 17:45:05

Zenodo大文件上传终极指南:告别网页限制,命令行一键搞定

Zenodo大文件上传终极指南&#xff1a;告别网页限制&#xff0c;命令行一键搞定 【免费下载链接】zenodo-upload upload big files to Zenodo using cURL, jq and bash 项目地址: https://gitcode.com/gh_mirrors/ze/zenodo-upload 还在为Zenodo大文件上传而烦恼吗&…

作者头像 李华
网站建设 2026/4/23 12:57:32

系统内存优化大师Mem Reduct:彻底解决电脑卡顿的终极方案

系统内存优化大师Mem Reduct&#xff1a;彻底解决电脑卡顿的终极方案 【免费下载链接】memreduct Lightweight real-time memory management application to monitor and clean system memory on your computer. 项目地址: https://gitcode.com/gh_mirrors/me/memreduct …

作者头像 李华
网站建设 2026/4/23 12:56:52

抖音下载器使用指南:轻松保存直播回放与视频内容

抖音下载器使用指南&#xff1a;轻松保存直播回放与视频内容 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 抖音作为当下最流行的短视频平台&#xff0c;每天都有大量精彩内容产生。但平台本身并不提供下载…

作者头像 李华