当前位置: 首页 > news >正文

C++ 位运算 高频面试考点 力扣 371. 两整数之和 题解 每日一题

文章目录

  • 题目解析
  • 为什么这道题值得你花几分钟弄懂?
  • 这道题的核心解法:位运算模拟加法
    • 二进制加法的本质
  • 完整位运算解法
  • 其他思路对比(仅作思路扩展)
    • 利用数组下标(仅限非负数)
    • 利用栈的深度(仅限非负数)
  • 扩展思考:位运算解法与计算机底层加法逻辑的关联
    • 本题解法如何复刻底层逻辑?
  • 面试避坑指南
  • 思考题
  • 下题预告

在这里插入图片描述
在这里插入图片描述

题目解析

题目链接:力扣 371. 两整数之和

题目描述:
给你两个整数  和  ,不使用 运算符  和  ,计算并返回两整数之和。

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

示例 2:
输入:a = 2, b = 3
输出:5

限制:

  1. -1000 <= a, b <= 1000

为什么这道题值得你花几分钟弄懂?

这道题是打破“常规运算思维”的经典题目——它强制我们跳出“直接用 + - 号计算”的惯性,深入理解计算机底层的二进制加法逻辑。其核心价值不在于“算出结果”,而在于掌握“位运算模拟算术运算”的核心思路,这是面试中考察“底层逻辑理解能力”的高频考点。

面试官考察这道题时,核心关注三点:

  1. 能否联想到“二进制加法拆分”,将求和拆分为“无进位加法”和“进位处理”两部分,体现对加法本质的理解;
  2. 能否用位运算分别实现“无进位加法”和“进位计算”,暴露对位运算特性的掌握程度;
  3. 能否处理“负数进位”的边界问题(即为何要用 unsigned int),彰显对计算机中“补码存储”的细节认知。

如果对位运算的基础特性(如异或、与、左移)有些生疏,建议先回顾位运算的核心规则:异或(^)可模拟“无进位相加”,与(&)+ 左移(<<1)可模拟“进位计算”,这是解决本题的核心工具。可以根据我的这篇博客进行理解回忆 位运算 常见方法总结 算法练习 C++

这道题的核心解法:位运算模拟加法

由于题目禁止使用 + - 运算符,我们必须回归加法的本质——二进制加法。在二进制中,两个数的加法可拆分为“无进位加法结果”和“进位值”两部分,重复处理这两部分直到无进位,最终结果即为总和。

二进制加法的本质

以十进制加法 13 + 9 = 22 为例,其二进制表示为 1101 + 1001 = 10110。我们可将其拆分为两步:

  1. 无进位加法(即异或):异或的本质就是无进位相加,即不考虑进位,对应位直接相加(0+0=0,0+1=1,1+1=0),结果为 0100(即十进制的 4);
    在这里插入图片描述

  2. 计算进位:仅保留产生进位的位(只有 1+1 会产生进位,进位值向左移 1 位),即我们可以用按位与统计哪个位要进位,在左移一位进行进位操作,结果为 10010(即十进制的 18);
    在这里插入图片描述

  3. 重复处理:将“无进位结果”与“进位值”再次执行上述两步,直到进位值为 0。此时无进位结果即为最终总和:
    第二次无进位加法:0100 + 10010 = 10110(无进位),进位值为 0,最终结果为 10110(十进制 22)。
    在这里插入图片描述

位运算如何实现这两步?
我们可以用三种位运算分别实现二进制加法的核心操作:

操作需求位运算实现原理说明
无进位加法a ^ b异或的特性:相同为 0(1^1=0),不同为 1(0^1=1),完全匹配“无进位相加”规则
计算进位值(a & b) << 11. 与运算(a&b):仅当对应位均为 1 时结果为 1,标记出“需要进位的位”;
2. 左移 1 位(<<1):进位值需传递到下一位,符合加法进位规则

完整位运算解法

基于上述原理,我们可以设计一个循环:不断用“无进位结果”更新 a,用“进位值”更新 b,直到 b 为 0(无进位),此时 a 即为最终总和。

1. 代码实现

class Solution {
public:int getSum(int a, int b) {while(b != 0)  // 当进位值为0时,循环结束,a即为结果{// 1. 计算无进位加法结果int sum = a ^ b;// 2. 计算进位值:用unsigned int避免负数进位的符号位问题unsigned int carry = (unsigned int)(a & b) << 1;// 3. 更新a为无进位结果,b为进位值,进入下一轮循环a = sum;b = carry;}return a;}
};

2. 关键解析:为什么要用 unsigned int
这是本题最容易被忽略的细节,也是面试中的高频考点——解决负数进位时的“符号位扩展”问题

背景:计算机中负数的存储方式
计算机用“补码”存储负数,最高位(符号位)为 1 表示负数。例如在 32 位系统中:

  • 十进制 -1 的二进制补码为 11111111 11111111 11111111 11111111(符号位为 1,其余位全 1);
  • 当对负数执行左移操作(<<1)时,若不处理符号位,编译器会进行“符号位扩展”(即保持符号位不变,填充 1 而非 0),导致进位值计算错误。

问题演示:若不用 unsigned int 会怎样?
假设 a = -1(补码 11111111),b = -1(补码 11111111):

  1. 计算 a & b:结果为 11111111(符号位为 1,表示负数);
  2. 直接左移 1 位((a&b) << 1):由于符号位扩展,结果会变成 11111110(仍为负数),而非正确的进位值 11111110(作为无符号数时表示十进制 254,即进位值应传递的正确值);
  3. 最终导致循环无法终止,或计算结果错误。

unsigned int 的作用
unsigned int(无符号整数)会强制编译器将变量视为“无符号数”,完全忽略符号位,左移时仅在右侧填充 0,避免符号位扩展导致的进位错误。即使原始 ab 是负数,通过 (unsigned int)(a & b) 转换后,也能正确计算进位值的二进制表示,确保循环正常终止。

3. 解法优劣势分析

优点缺点
✅ 完全符合题目要求:不使用 + - 运算符⚠️ 逻辑依赖二进制基础:需理解补码、位运算特性,对新手不友好
✅ 时间复杂度 O(1):循环次数最多为整数的位数(如 32 位系统最多 32 次),可视为常数时间⚠️ 需处理符号位细节:必须用 unsigned int 避免负数进位错误,否则会出 bug
✅ 空间复杂度 O(1):仅用几个变量存储中间结果,无额外空间开销
✅ 通用性强:适用于正负数、零的所有组合,无边界限制

注:每次进位至少将最高位的1左移一位,而32位整数的符号位占1位,因此最多左移31次后,进位值会超出表示范围而“自然溢出”为0,故循环次数不超过32次。

其他思路对比(仅作思路扩展)

虽然本题的最优解是位运算,但为了更全面地理解“禁止 + - 时的求和方式”,以下两种思路可作为对比(实际面试中不推荐,效率或通用性差):

利用数组下标(仅限非负数)

核心思路:创建一个长度为 a+1 的数组,再通过数组下标访问 b 次,最终下标即为 a+b
局限性

  • 无法处理负数(数组下标不能为负);
  • ab 较大时(如 1000),数组会占用大量冗余空间,效率极低。

代码示例

class Solution {
public:int getSum(int a, int b) {// 仅适用于a、b为非负数的情况if (a < 0 || b < 0) return -1; // 负数处理不了char arr[a + 1]; // 创建长度为a+1的数组return (int)(&arr[b] - arr); // 下标差即为a+b}
};

利用栈的深度(仅限非负数)

核心思路:通过递归调用栈的深度模拟加法,递归 a 次后再递归 b 次,栈的深度即为总和。
局限性

  • 无法处理负数;
  • 递归深度过大时(如 a+b=1000)会触发栈溢出,程序崩溃。

代码示例

class Solution {
public:int getSum(int a, int b) {if (b == 0) return a;// 递归一次相当于b减1,a加1,直到b为0return getSum(a + 1, b - 1); }
};

扩展思考:位运算解法与计算机底层加法逻辑的关联

我们必须先明确一个核心事实:我们的位运算解法,本质上是对计算机底层处理+-运算的逻辑复刻。计算机硬件层面并不直接识别“+”和“-”这类符号,而是通过补码编码与全加器电路,将加减法统一为二进制位运算与进位处理,而这正是本题解法的设计依据

计算机底层如何处理+-

计算机处理加减法的核心机制可概括为"一套电路、两种运算":

  1. 存储基础:补码编码

    • 计算机中所有整数(包括正数、负数)都以"补码"形式存储,这是实现加减统一的关键。
    • 正数补码=原码(符号位为0,数值位为二进制绝对值)
    • 负数补码=绝对值的反码+1(符号位为1,确保减法可转化为加法)
    • 举例:8位系统中,-3的补码是11111101(3的原码00000011→反码11111100→+1→11111101
  2. 加法实现:全加器电路

    • 硬件核心是"全加器"电路,它能处理两个二进制位的相加并考虑低位进位:
      • 本位和 = 被加数 ^ 加数 ^ 低位进位(异或运算实现无进位相加)
      • 向高位进位 = (被加数 & 加数) | (被加数 & 低位进位) | (加数 & 低位进位)(与运算识别进位位)
    • 32位整数加法通过32个全加器串联实现,低位进位逐位传递到高位,直到最高位
  3. 减法实现:转化为加法

    • 计算机没有专门的减法器,a - b会被自动转换为a + (-b)
    • -b通过"对b的补码取反加1"获得(与补码的定义一致)
    • 最终仍通过加法器完成运算,实现了"一套硬件电路处理两种运算"

本题解法如何复刻底层逻辑?

我们的位运算解法与计算机底层加法逻辑形成了完美映射:

计算机底层机制本题位运算实现对应代码
无进位加法计算异或运算 a ^ bsum = a ^ b
进位值计算与运算+左移 (a & b) << 1carry = (unsigned int)(a & b) << 1
进位传递循环循环处理进位直到无进位while(b != 0) { ... }
补码处理负数直接对补码执行位运算无需额外处理,直接操作ab
避免符号位扩展硬件自动按无符号处理进位unsigned int强制无符号左移

-1 + 2的计算为例:

  • 底层:-1的补码111111112的补码00000010通过全加器逐位计算
  • 本题:a ^ b得到无进位结果11111101(-3),(a & b) << 1得到进位00000100(4),循环处理直到进位为0

这种对应关系揭示了一个重要事实:本题要求"不用+和-实现求和",本质上是让我们手动实现一次计算机硬件的加法过程。我们用软件代码模拟了硬件电路的逻辑,这就是解法的根本依据。

理解了这层关联,不仅能掌握本题解法,更能触类旁通——所有位运算模拟算术运算的题目(如乘法、除法),其本质都是对计算机底层运算逻辑的软件复现。

面试避坑指南

  1. 忘记处理负数进位:若不用 unsigned int 转换进位值,负数求和会因符号位扩展导致循环无法终止,这是最常见的错误,必须主动提及并解释;
  2. 循环条件错误:循环条件应为 b != 0(而非 a != 0),因为我们需要等待“进位值”消失,而非“无进位结果”消失;
  3. 混淆无进位加法和进位计算:记住“异或算无进位,与+左移算进位”,不要颠倒两者的作用;
  4. 忽略补码知识:面试中可能会被追问“负数如何用位运算求和”,需简要说明“计算机用补码存储负数,位运算可直接对补码操作,无需额外处理符号”。

思考题

如果题目允许使用 + - 运算符,但禁止使用 * / 运算符,如何计算两整数的乘积?
(提示:同样可用位运算,将乘法拆分为“左移”和“加法”,例如 a*3 = a*2 + a = (a << 1) + a
可以用“俄罗斯农民乘法”或“二进制拆分法”,你能写出最优版本吗?欢迎评论区贴代码,我会选最优答案置顶!

下题预告

137. 只出现一次的数字 II

下一篇将讲解力扣 137. 只出现一次的数字 II,带你跳出 “异或直接消去重复” 的思维惯性,解锁位运算 “按位统计次数、模运算筛选唯一” 的核心逻辑——当数组中除一个元素外,其余元素均出现三次时,如何用常数空间、线性时间精准定位那个唯一元素,将是我们深入探讨的重点,尤其会聚焦 “位级计数” 这一面试高频的位运算进阶技巧。

如果这篇内容对你觉得不错,别忘了 点赞👍 + 收藏⭐ + 关注👀 哦!
有问题欢迎在评论区留言,我会认真思考并及时回复!

在这里插入图片描述

http://www.dtcms.com/a/427069.html

相关文章:

  • 网络安全常见敏感目录字典
  • React学习(三)--- 组件化开发编写css
  • 设计模式(C++)详解——观察者模式(Observer)(1)
  • 网站建设报表明细新手做网站看什么书
  • 微课网站开发如何查看网站域名
  • Spring工程 生成表和mapper文件
  • 服装培训网站建设网站图片切换
  • Python爬虫实战:获取丁香人才网招聘信息与数据分析
  • 光学转镜最小长度计算模型:基于视场角与有效口径的匹配算法
  • 汉子由来 外国人做的网站网页设计的尺寸是指
  • 智能驱动与合规双赢:2025年企业DevOps平台选型深度解析
  • 2025年,如何选择Python Web框架:Django, Flask还是FastAPI?
  • FLASK与JAVA的多文件互传(多文件互传亲测)
  • 蓝牙音箱的技术演进:从便捷到高保真的音频革命
  • 打破信息孤岛,构建统一视界:视频融合平台EasyCVR在智慧校园建设中的核心作用
  • 计算机应用技术网站开发基础知识网店推广平台
  • 快速完美解决在CefSharp.WinForms.ChromiumWebBrowser浏览器中无法播放视频的问题
  • 【高并发服务器:前置知识】一、项目介绍 模块划分
  • 数据结构入门 (五):约束即是力量 —— 深入理解栈
  • 如何搭建网站的结构丰台专业网站建设公司
  • Web渗透之一句话木马
  • 网站建设如何选择服务器百度做公司网站多少钱
  • Vscode+CMake编译时出现中文乱码
  • 38、spark读取hudi报错:java.io.NotSerializableException: org.apache.hadoop.fs.Path
  • 三年级上册语文快乐读书吧读书笔记+知识点(格林童话、安徒生童话、稻草人)+三年级语文快乐读书吧笔记汇总+完整电子版可下载打印
  • 迅为Hi3516CV610开发板强劲内核-海思Hi3516CV610核心板
  • 网站开发可以当程序员wordpress 怎么迁移
  • babelfish for postgresql 分析--babelfishpg_tds--doing
  • 手机网站排行榜焦作专业网站建设费用
  • 小程序开发:开启定制化custom-tab-bar但不生效问题,以及使用NutUI-React Taro的安装和使用