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

位运算算法实战:经典题目深度解析

综述由AI生成位运算在算法设计中具有极高的效率优势。通过六个经典案例,展示了如何利用位图思想判定字符唯一性,借助异或消去特性寻找缺失数字,模拟硬件加法器实现整数求和,以及通过比特位统计和分组策略解决单一数字识别问题。这些技巧不仅提升了代码执行效率,也体现了底层逻辑优化的重要性。

GopherDev发布于 2026/3/25更新于 2026/5/2124 浏览

位运算算法实战:经典题目深度解析

位运算在底层逻辑优化中扮演着关键角色,理解其特性往往能让代码更简洁高效。下面通过六个典型场景,梳理位运算的核心用法与解题思路。

判定字符是否唯一

问题描述: 判断字符串中的字符是否全部唯一。

核心思路: 利用【位图】思想,用一个整数的比特位代表字符状态。32 位的 int 足以覆盖所有小写字母。若某位为 0 表示未出现,为 1 则表示已出现。这里还可以结合鸽巢原理进行快速剪枝。

class Solution {
public:
    bool isUnique(string astr) {
        // 利用鸽巢原理优化,超过 26 个字符必有重复
        if (astr.size() > 26) return false;
        
        int bitmap = 0;
        for (auto i : astr) {
            int e = i - 'a';
            // 先判断该字符是否出现过
            if (((bitmap >> e) & 1) == 1) return false;
            // 将当前字符加入到位图中
            bitmap |= (1 << e);
        }
        return true;
    }
};

寻找消失的数字

问题描述: 数组包含 [0, n] 中缺失的一个数字,找出它。

核心思路: 利用异或运算的【消消乐】规则。将数组中的所有数与 [0, n] 范围内的所有数一起异或,成对的数字会相互抵消,最终剩下的就是缺失的那个数字。

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int ret = ;
        
         ( i : nums) ret ^= i;
        
         ( i = ; i <= nums.(); i++) ret ^= i;
         ret;
    }
};
0
// 异或数组中的所有元素
for
auto
// 异或 [0, n] 范围内的所有数字
for
int
0
size
return

两整数之和

问题描述: 不使用 + 和 - 运算符计算两个整数的和。

核心思路:

  • 异或 ^ 本质是【无进位加法】;
  • 按位与 & 配合左移能得到【进位】;
  • 循环执行直到进位变为 0。

注意处理负数时的符号位扩展问题,使用 unsigned int 存储进位更安全。

class Solution {
public:
    int getSum(int a, int b) {
        while (b) {
            int x = a ^ b;              // 无进位相加的结果
            unsigned int carry = (a & b) << 1; // 计算进位
            a = x;
            b = carry;
        }
        return a;
    }
};

只出现一次的数字 II

问题描述: 数组中除一个元素外,其余每个元素都恰好出现三次,找出那个唯一的元素。

核心思路: 统计每一位上 1 出现的总次数。对于目标数字的某一位,如果它在数组中出现一次,那么该位总和 % 3 应该等于 1;否则为 0。通过遍历 32 个比特位即可还原出结果。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for (int i = 0; i < 32; i++) { // 依次检查每一位
            int sum = 0;
            for (auto x : nums)
                if (x & (1 << i)) sum++;
            sum %= 3;
            if (sum & 1) ret |= (1 << i);
        }
        return ret;
    }
};

只出现一次的数字 III

问题描述: 数组中有两个元素只出现一次,其余都出现两次,找出这两个数。

核心思路:

  1. 将所有数异或,结果为两个目标数的异值 a ^ b。
  2. 找到 a 和 b 二进制中不同的某一位(即异或结果中为 1 的位)。
  3. 根据这一位将数组分为两组,分别异或,即可得到两个答案。
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        // 1. 将所有数异或在一起
        int tmp = 0;
        for (auto x : nums) tmp ^= x;
        
        // 2. 找出 a, b 中比特位不同的那一位
        int diff = 0;
        while (!((tmp >> diff) & 1)) diff++;
        
        // 3. 根据 diff 位的不同,将所有数划分成两类
        int a = 0, b = 0;
        for (auto x : nums) {
            if ((x >> diff) & 1) b ^= x;
            else a ^= x;
        }
        return {a, b};
    }
};

消失的两个数字

问题描述: 数组中包含 [1, n+2] 中缺失的两个数字。

核心思路: 这道题是前两道题的组合。先将数组中的数和 [1, n+2] 区间内的所有数【异或】在一起,问题就转化为'有两个数出现一次,其余出现两次',直接复用上述分组策略即可。

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        // 1. 将所有数异或在一起
        int tmp = 0;
        for (auto x : nums) tmp ^= x;
        for (int i = 1; i <= nums.size() + 2; i++) tmp ^= i;
        
        // 2. 找出 a, b 中比特位不同的那一位
        int diff = 0;
        while (!((tmp >> diff) & 1)) diff++;
        
        // 3. 根据 diff 位的不同,将所有数划分成两类
        int a = 0, b = 0;
        for (auto x : nums) {
            if ((x >> diff) & 1) b ^= x;
            else a ^= x;
        }
        for (int i = 1; i <= nums.size() + 2; i++) {
            if ((i >> diff) & 1) b ^= i;
            else a ^= i;
        }
        return {a, b};
    }
};

目录

  1. 位运算算法实战:经典题目深度解析
  2. 判定字符是否唯一
  3. 寻找消失的数字
  4. 两整数之和
  5. 只出现一次的数字 II
  6. 只出现一次的数字 III
  7. 消失的两个数字
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • Stable Diffusion 底模与 VAE 搭配指南:提升生成质量的核心策略
  • PyTorch 核心机制:自动微分与雅可比向量积详解
  • AIGC 核心概念解析:22 个基础术语详解
  • 动态规划:子数组与子串问题实战
  • 五大经典排序算法详解:插入、希尔、冒泡、选择与堆排序
  • 线性动态规划经典四题实战解析
  • Effective Java 第 32 条:谨慎并用泛型和可变参数
  • 循环队列(Circular Queue)详解
  • AI 驱动的对话式 PCB 设计工具实战与展望
  • Neo4j Desktop 2.0 安装及自定义路径配置指南
  • 前缀和算法实战:从一维到二维及哈希结合应用
  • Java 实现线性方程组求解:LU 分解与部分主元法
  • 缓存算法:LRU 与 LFU 原理及 Java 实现
  • OpenClaw 飞书机器人权限配置与安全指南
  • 91n 网络环境下最优 TensorFlow 镜像拉取方案
  • 无人机视觉目标检测数据集 VisDrone 详解
  • 基于 Redis 与 Caffeine 的图片系统性能优化及分布式 Session 实践
  • AI 智能体工具:OpenCode、OpenClaw 安装与配置指南
  • 三维模型数据结构与存储方式解析
  • C++ 模板初阶:泛型编程基础

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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