跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

算法实战:位运算解决整数求和、唯一数与缺失数字

位运算技巧在算法题中的应用实例。首先利用异或和按位与实现无进位加法循环处理进位;其次统计比特位总和模三还原唯一数字;最后通过分组异或定位缺失的两个数值。涵盖整数求和、单次出现数字及数组缺失值问题,提供 C++ 高效解法。

灰度发布发布于 2026/3/24更新于 2026/6/1522 浏览
算法实战:位运算解决整数求和、唯一数与缺失数字

两整数之和

题目描述

不使用运算符 + 和 -,计算两个整数 a 和 b 的和。

题目示例

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

解法(位运算)

核心思路
  • 异或 ^ 运算本质是【无进位加法】。
  • 按位与 & 操作能够得到【进位】的对应位置,但还需要左移 1 才是需要进位的位置。
  • 然后一直循环,直到【进位】变成 0 为止。
代码实现
class Solution {
public:
    int getSum(int a, int b) {
        // 解法:位运算 (^ 异或:无进位相加)
        while (b) {
            int x = a ^ b;
            int y = (a & b) << 1;
            a = x;
            b = y; // 得到进位的对应位置,再左移 1 才是需要进位的位置
                   // 只进行一次 a & b 不一定保证新的 a 和 b 没有需要进位的位置,
                   // 所以需要将这个步骤进行循环。a & b 为 0 则说明没有进位的位置了
        }
        return a ^ b;
    }
};
流程解析

文章配图

只出现一次的数字 II

题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

题目示例

输入:[2,2,3,2] 输出:3

解法(比特位计数)

核心思路

设要找的数为 ret。由于整个数组中,需要找的元素只出现了【一次】,其余的数都出现【三次】,因此我们可以根据所有数的【某一个比特位】的总和 % 3 的结果,快速定位到 ret 上的【一个比特位上】的值是 0 还是 1。这样我们通过 ret 的每一个比特位上的值,就可以将 ret 还原出来。

代码实现
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        // 方法一:排序 (时间复杂度较大:O(NlogN),但容易想到)
        // sort(nums.begin(), nums.end());
        // for(int i = 0; i < nums.size() - 1; i += 3) {
        //     if(nums[i] != nums[i + 1]) {
        //         return nums[i];
        //     }
        // }
        // return nums.back();

        // 方法二:位运算 (为线性时间复杂度:O(32N),但非常巧妙比较难想)
        int ret = 0; // 作为位图
        for (int i = 0; i < 32; i++) { // 一个数二进制位的长度,依次修改 ret 的每一位
            int sum = 0;
            for (int x = 0; x < nums.size(); x++) { // 计算 nums 中所有数的二进制第 i 位的和
                sum += ((nums[x] >> i) & 1);
            }
            ret |= ((sum % 3) << i); // 求和结果余 3 后修改到 ret 对应第 i 位的位置
        }
        return ret;
    }
};
流程解析

文章配图

消失的两个数字

题目描述

给定一个包含从 0 到 n 的所有整数的数组,其中有两个数字消失了。找出这两个消失的数字。

题目示例

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

解法(位运算)

核心思路

本题相当于就是 268.丢失的数字 + 260.只出现一次的数字 III 组合起来的题。先将数组中的数和【1,n+2】区间内的所有数【异或】在一起,问题就变成了:有两个数出现了【一次】,其余所有的数出现了【两次】。进而变成了 260.只出现了一次的数字 III 这道题。

代码实现
class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        // 位运算
        // 先将数组 nums 所有数以及 1~N+2 区间所有数全部异或一遍,得到消失两数的异或
        int ret = 0;
        int a = 0;
        int b = 0; // 分别表示两个消失的数

        for (int i = 0; i < nums.size(); i++) {
            ret ^= nums[i];
        }
        for (int i = 1; i <= nums.size() + 2; i++) {
            ret ^= i;
        }

        // 此时 ret = a ^ b
        // 由于 a 和 b 一定不同,所以一定会存在某一位比特位一个是 0 一个是 1
        // 两者异或后对应的那一位就一定是 1,所以我们需要找到那一位
        // 获取到 ret 最右侧出现 1 的比特位位置
        int x = 0;
        while (1) {
            if (((ret >> x) & 1) == 1) {
                break;
            }
            x++;
        }

        // 将数组 nums 所有数以及 (1~N+2) 区间所有数分成两类:
        // 一类就是第 x 位比特位值为 0,一类就是第 x 位比特位值为 1
        // 这样两个消失数就会被分开,通过异或,在数组以及 (1~N+2) 区间都出现的数就会抵消,
        // a 和 b 也就分别是这两个消失数了
        for (int i = 0; i < nums.size(); i++) {
            if (((nums[i] >> x) & 1) == 0) // 假设 a 是第 x 位比特位为 0 的消失数
                a ^= nums[i];
            else // 假设 b 就是第 x 位比特位为 1 的消失数
                b ^= nums[i];
        }
        for (int i = 1; i <= nums.size() + 2; i++) {
            if (((i >> x) & 1) == 0)
                a ^= i;
            else
                b ^= i;
        }
        // 两次循环则数组中存在的数异或了两次被抵消,a 和 b 就分别是两个消失数
        return {a, b};
    }
};
流程解析

文章配图

目录

  1. 两整数之和
  2. 题目描述
  3. 题目示例
  4. 解法(位运算)
  5. 核心思路
  6. 代码实现
  7. 流程解析
  8. 只出现一次的数字 II
  9. 题目描述
  10. 题目示例
  11. 解法(比特位计数)
  12. 核心思路
  13. 代码实现
  14. 流程解析
  15. 消失的两个数字
  16. 题目描述
  17. 题目示例
  18. 解法(位运算)
  19. 核心思路
  20. 代码实现
  21. 流程解析
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Faster-Whisper 热词详解与实战配置
  • 大疆无人机如何导出日志并解析
  • ComfyUI 入门:ControlNet 节点与预处理器使用指南
  • 算法视角下的数组基础:定义、操作与场景
  • 在线图书借阅平台的设计与实现
  • Telegram Android 官方开源客户端源码解析与定制指南
  • 基于 Qlib 与 RD-Agent 的 AI 量化系统搭建实战
  • 半小时基于 OpenClaw 搭建 AI 量化系统:开源三件套实测
  • 基于 LeRobot 的手机 AR 机器人远程控制实现
  • GitHub 日榜热门项目 (2025-11-16)
  • 使用谷歌云端硬盘部署 Stable Diffusion 个人 AI 绘画环境
  • 星辰 RPA 与 Agent:构建小红书自动发文机器人
  • OpenClaw 安全指南:理性使用 AI 工具
  • 百考通 AIGC 检测工具功能解析与使用体验
  • AI 大模型开发核心技能体系与学习路径
  • ExcelJS 使用教程:JavaScript Excel 处理库
  • GitHub Copilot 接入第三方 OpenAI 兼容模型及去除安全限制方法
  • SpringBoot + jQuery 实战:从零搭建留言板
  • 颜色透明度百分比与十六进制换算指南
  • Docker 部署 OpenJDK 指南:替代方案、步骤与最佳实践

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online