35. 两个整数之和
题目描述
不使用运算符 + 和 -,计算两个整数 a 和 b 的和。
解题思路
这道题的核心在于理解计算机底层是如何做加法的。我们可以把加法拆解为两部分:
- 无进位加法:使用异或运算
^。比如1 ^ 1 = 0,1 ^ 0 = 1,这正好对应二进制加法中不考虑进位的结果。 - 进位处理:使用按位与
&并左移一位<< 1。只有当两个位都是 1 时才会产生进位,且进位要加到更高一位上。
我们需要不断重复这两个步骤,直到没有进位为止(即进位值为 0),此时 a 就是最终结果。
C++ 代码实现
class Solution {
public:
int getSum(int a, int b) {
while (b != 0) {
// 无进位和
int sumWithoutCarry = a ^ b;
// 进位值
int carry = (unsigned int)(a & b) << 1;
a = sumWithoutCarry;
b = carry;
}
return a;
}
};
注意:在 C++ 中,对有符号整数进行左移可能会触发未定义行为,因此建议将
(a & b)强制转换为无符号类型后再左移,或者确保逻辑安全。这里为了严谨性做了转换处理。
36. 只出现一次的数字 II
题目描述
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
解题思路
既然其他数字都出现了三次,那么对于任意一个二进制位,如果该位是 1,它在所有数字的总和中应该是 3 的倍数(如果是目标数字则该位贡献 1)。
我们可以统计数组中所有数字在每个比特位上的总和,然后对 3 取模。如果余数是 1,说明目标数字在该位上是 1;否则是 0。通过遍历 32 个比特位,就能还原出目标数字。
这种方法的时间复杂度是 O(32N),空间复杂度 O(1),非常高效。
C++ 代码实现
class Solution {
public:
{
ret = ;
( i = ; i < ; i++) {
sum = ;
( x : nums) {
sum += ((x >> i) & );
}
(sum % != ) {
ret |= ( << i);
}
}
ret;
}
};


