1 题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
示例:
输入: a = 1, b = 1
输出: 2
提示:
a, b 均可能是负数或 0
结果不会溢出 32 位整数
2 解题思路
本题考查对位运算的灵活使用,即使用位运算实现加法。
设两数字的二进制形式a,b,其求和s=a+b,a(i)代表a的二进制第i位,则分为以下四种情况:
a(i) | b(i) | 无进位和n(i) | 进位c(i+1) |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
观察发现,无进位和与异或运算规律相同,进位和与运算规律相同(并需左移一位)。因此,无进位和n与进位c的计算公式如下:
{ n = a ⊕ b 非 进 位 和 : 异 或 运 算 c = a & b < < 1 进 位 : 与 运 算 + 左 移 一 位 \left\{ \begin{array}{lcl} n=a \oplus b & & {非进位和:异或运算}\\ c = a \& b << 1 & & {进位:与运算+左移一位} \end{array} \right. {
n=a⊕bc=a&b<<1非进位和:异或运算进位:与运算+左移一位
和 s = 非 进 位 和 n + 进 位 c 和s=非进位和n+进位c 和s=非进位和n+进位c。即可将s=a+b转化为:
s = a + b ⇒ s = n + c s = a + b \Rightarrow s = n + c s=a+b⇒s=n+c
循环求n和c,直至进位c=0;此时s=n,返回n即可。
Q:若数字a和b中有负数,则变成了减法,如何处理?
A:在计算机系统中,数值一律用补码来表示和存储。补码的优势:加法、减法可以统一处理(CPU只有加法器)。因此,以上方法同时适用于正数和负数的加法。
class Solution {
public int add(int a, int b) {
while (b != 0) {
int c = (a & b) << 1;
a ^= b;
b = c;
}
return a;
}
}
复杂度分析:
- 时间复杂度 O(1) : 最差情况下(例如 a= 0x7fffffff , b=1 时),需循环 32 次,使用 O(1) 时间;每轮中的常数次位操作使用 O(1) 时间。
- 空间复杂度 O(1) : 使用常数大小的额外空间。