Go&Java算法之不用加减乘除做加法

472 阅读2分钟

这是我参与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;
    }
};