class UnusualAdd {
public:
int addAB(int A, int B) {
// write code here
if(B == 0)
return A;
return (addAB(A^B,(A&B)<<1 ));
}
};
解题思路全解析
这段代码是用递归 + 位运算模拟二进制加法的经典实现,核心是复刻计算机底层的加法逻辑(无进位相加 + 进位处理),全程不使用算术运算符(+/-等),完全符合“非常规加法”的题目要求。以下分4层拆解思路:
一、核心原理:二进制加法的本质
计算机做加法时,二进制层面只分两步,这也是代码的核心逻辑根基:
1. 无进位相加 |
(异或) | 异或规则:相同位为0,不同位为1 → 刚好对应“二进制相加但不考虑进位”的结果(比如
本位得0,
本位得1)。 |
2. 计算进位 |
| ①
(按位与):只有两个位都为1时结果为1 → 精准定位“需要进位的位”;②
(左移1位):进位要加到更高一位,左移刚好实现“进位挪位”。 |
算法核心逻辑:
把“无进位和”和“进位值”重新作为新的两个数继续相加,直到进位值为0(没有需要处理的进位),此时的“无进位和”就是最终结果。
二、递归逻辑拆解(代码逐行解读)
class UnusualAdd {
public:
int addAB(int A, int B) {
// 终止条件:进位B为0,说明所有进位处理完毕,当前A就是最终和
if(B == 0)
return A;
// 递归调用:新的加数是“无进位和”和“进位值”,继续相加
return (addAB(A^B,(A&B)<<1 ));
}
};
1. 终止条件:if(B == 0) return A
B的含义:递归过程中,B始终代表“当前需要处理的进位值”;- 当
B=0时,说明没有任何进位需要处理了,此时的A是“所有位无进位相加 + 所有进位处理完成”的最终结果,直接返回即可。
2. 递归调用:addAB(A^B, (A&B)<<1)
递归的核心是“更新两个加数”,让加法持续进行直到无进位:
- 第一个参数
A^B:把本轮“无进位相加的结果”作为下一轮的新A; - 第二个参数
(A&B)<<1:把本轮“计算出的进位值”作为下一轮的新B; - 每一轮递归都是在“处理上一轮的进位”,直到进位为0。
三、具体例子验证(直观理解递归过程)
以 A=3(二进制 11) + B=1(二进制 01) 为例,逐轮拆解递归步骤:
1(初始) | 3(11) | 1(01) | 11^01=10(2) | (11&01)<<1=01<<1=10(2) | 递归调用 addAB(2, 2) |
2 | 2(10) | 2(10) | 10^10=00(0) | (10&10)<<1=10<<1=100(4) | 递归调用 addAB(0, 4) |
3 | 0(000) | 4(100) | 000^100=100(4) | (000&100)<<1=000<<1=0 | 递归调用 addAB(4, 0) |
4 | 4(100) | 0 | - | - | 触发终止条件,返回4 |
最终结果 4(3+1=4),完全正确。
四、关键细节(新手避坑)
- 递归的本质是“循环处理进位”: 递归没有新增逻辑,只是把“重复计算无进位和 + 进位”的过程用递归代替了循环,终止条件就是“无进位可处理”。
- 补码的自动处理:
C++ 中
int是补码存储,位运算会自动处理负数加法(比如A=-1+B=2),无需额外判断符号位,递归逻辑对正负值都生效。 - 左移1位的必要性:
比如
A=1(01)+B=1(01),A&B=01表示第0位有进位,左移1位后变成10(2),代表“进位要加到第1位”,这是进位的核心规则。
核心思路总结
- 底层逻辑:用位运算复刻二进制加法的两步法(无进位相加
^+ 进位计算&<<1); - 递归设计:以“进位值B”为终止条件,每轮递归更新“无进位和”和“进位值”,直到无进位;
- 效率特点:时间复杂度
O(log n)(n为数值大小,进位最多左移log₂(n)次),空间复杂度O(log n)(递归调用栈深度),是“无算术运算符加法”的最优解法之一。
这个思路的核心是“跳出十进制思维,回归二进制加法本质”,也是面试中考察位运算的高频考点。

京公网安备 11010502036488号