这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战
不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
示例:
输入: a = 1, b = 1
输出: 2
提示:
a, b 均可能是负数或 0
结果不会溢出 32 位整数
题解
算法一:位运算(Java)
平时我们进行数学计算的使用的 “ + - * / ” 这些数学运算符,运算单位只有一种: 十进制。
而这题要求,不使用 运算符 “+”、“-”、“*”、“/” ,其实就是 不让 我们使用 十进制 来做计算。
这很容易就想到使用计算机本身的 二进制 代替 十进制 做计算。
需要注意的是,不使用 “+”、“-”、“”、“/”,是不使用十进制,而 “+”、“-”、“”、“/” 法,背后的 加法思想 减法思想 还是可以使用的。 并且二进制、八进制、十进制、十六进制等等 计算思想 是统一不变的。 只是因为它们的进制形式不一样,带来的处理方式不一样。
这题最根本的问题,可能不是使用什么方法来完成加减的问题,而是一个怎么计算的问题。
设两数字的二进制形式 a, b,其求和 s = a + b ,a(i) 代表 a 的二进制第 i 位。
无进位和 与 异或运算 规律相同,进位 和 与运算 规律相同(并需左移一位)。因此,无进位和 n 与进位 c 的计算公式如下;
n=a⊕b —— 非进位和:异或运算
c=a&b<<1 —— 进位:与运算+左移一位
(和 s )==(非进位和 n )+(进位 c )。即可将 s = a + b 转化为: s=a+b⇒s=n+c
循环求 n 和 c ,直至进位 c = 0 ;此时 s = n ,返回 n 即可。
class Solution {
public int add(int a, int b) {
while (b != 0) {
int temp = a ^ b;
b = (a & b) << 1;
a = temp;
}
return a;
}
}
时间复杂度:O(1)
空间复杂度:O(1)
算法一:位运算(Go)
func add(a int, b int) int {
// 进位
var carry int
for b != 0 {
// 进位
carry = (a & b) << 1
// 不进位加
a ^= b
// 加进位
b = carry
}
return a
}
算法一:位运算(C++)
class Solution {
public:
int add(int a, int b) {
while (b) {
int carry = a & b; // 计算 进位
a = a ^ b; // 计算 本位
b = (unsigned)carry << 1;
}
return a;
}
};