算法实战:位运算解决两数之和、唯一数字与缺失数字
在算法面试中,位运算往往能带来意想不到的空间和时间复杂度优化。今天我们来深入探讨三道经典题目,看看如何利用异或、按位与和比特位计数来解决整数求和、寻找单一元素以及查找缺失数字的问题。
35. 两个整数之和
题目描述
不使用运算符 + 和 -,计算两整数 a、b 之和。
解题思路
这道题的核心在于理解计算机底层是如何做加法的。我们可以将加法拆解为两个部分:
- 无进位加法:通过异或运算
^实现。例如1 ^ 1 = 0,1 ^ 0 = 1,这正好对应了二进制加法中不考虑进位的结果。 - 进位计算:通过按位与
&获取需要进位的位置,然后左移一位<< 1才是真正需要加到高位上的值。
只要进位不为 0,就需要重复上述过程,直到没有进位为止。
代码实现
class Solution {
public:
int getSum(int a, int b) {
// 当进位 b 不为 0 时,继续循环
while (b != 0) {
// 无进位相加的结果
int sumWithoutCarry = a ^ b;
// 计算进位位置并左移
int carry = (unsigned int)(a & b) << 1;
a = sumWithoutCarry;
b = carry;
}
return a;
}
};
注意:在 C++ 中,对有符号整数进行右移或左移可能涉及未定义行为,这里为了安全起见,计算进位时建议强制转换为无符号类型处理,或者确保逻辑正确。
36. 只出现一次的数字 II
题目描述
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
解题思路
既然其他数字都出现了三次,那么对于每一个二进制位来说,所有数字在该位上为 1 的总次数一定是 3 的倍数(如果该位属于重复数字)或者是 3 的倍数加 1(如果该位属于目标数字)。
因此,我们可以统计所有数字在每一位上 1 出现的总次数,然后对 3 取余。如果余数为 1,说明目标数字在这一位上是 1;否则是 0。通过遍历 32 个比特位,即可还原出目标数字。


