leetcode每日一题系列——不用加减乘除做加法

283 阅读1分钟

这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战

题目描述

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

示例:

输入: a = 1, b = 1
输出: 2

提示:

ab 均可能是负数或 0
结果不会溢出 32 位整数

题解

方法一:位运算

解题思路

本题考查对位运算的灵活使用,即使用位运算实现加法。

设两数字的二进制形式 a,b,其求和 s = a + b,a(i) 代表 a 的二进制第 i 位,则分为以下四种情况:

a(i)b(i)无进位和 n(i)进位 c(i+1)
0000
0110
1010
1101

观察发现,无进位和 与 异或运算 规律相同,进位 与 与运算 规律相同(并需左移一位)。因此,无进位和 n 与进位 c 的计算公式如下:

n = ab      非进位和:异或运算
c = a & b << 1 进位:与运算 + 左移一位

(和 s)= (非进位和 n) + (进位 c)。即可将 s = a + b 转化为:s = a + b => s = n + c

循环求 n 和 c,直至进位 c = 0;此时 s = n,返回 n 即可。

image.png

Q : 若数字 aa 和 bb 中有负数,则变成了减法,如何处理?
A : 在计算机系统中,数值一律用 补码 来表示和存储。补码的优势: 加法、减法可以统一处理(CPU只有加法器)。因此,以上方法 同时适用于正数和负数的加法 。

代码

class Solution {
    public int add(int a, int b) {
        while(b != 0) { // 当进位为 0 时跳出
            int c = (a & b) << 1;  // c = 进位
            a ^= b; // a = 非进位和
            b = c; // b = 进位
        }
        return a;
    }
}

复杂度分析

时间复杂度O(1)  :最差情况下(例如 a = 0x7fffffff,b = 1 时),需循环 32 次,使用 O(1) 时间;每轮中的常数次位操作使用 O(1) 时间。
空间复杂度O(1)  :使用常数大小的额外空间。

个人理解

以 9 + 7 为例,详细手动模拟一下步骤:

十进制模拟

第一次循环,计算 9 + 7:

无进位和:9 + 7 = 6。
进位:个位进一位为 1,进到十位了,所以要 * 10,即 10。

第二次循环,计算 6 + 10:

无进位和

个位:0 + 6 = 6
十位:1 + 0 = 1

结果为 16

进位:个位无进位,十位无进位,

所以最终结果为 16。

二进制模拟

9 的二进制为:1001
7 的二进制位:111

第一次循环,计算 1001 + 111:

无进位和(异或) :1001 ^ 111 = 1110
进位(与) :1001 & 111 = 1

十进制进位就应该 x10,二进制进位就得左移一位,所以 1 << 1 = 10

第二次循环,计算 1110 + 10:

无进位和(异或) :1110 ^ 10 = 1100
进位(与) :1110 & 10 << 1 = 10 < < 1 = 100

第三次循环,计算 1100 + 100:

无进位和(异或) :1100 ^ 100 = 1000
进位(与) :1100 & 100 << 1 = 100 < < 1 = 1000

第四次循环,计算 1000 + 1000:

无进位和(异或) :1000 ^ 1000 = 0000
进位(与) :1000 & 1000 << 1 = 1000 < < 1 = 10000

第五次循环,计算 0000 + 10000:

无进位和(异或) :0000 ^ 10000 = 10000
进位(与) :0000 & 10000 << 1 = 00000 < < 1 = 000000

这个时候就该结束了,因为此时无进位了。

此时 10000 的值就是最终结果,换成十进制为 16。

为什么十进制相加循环次数这么少?而二进制循环次数这么多呢? 因为二进制位数多,碰到特别情况,比如该情况,一位一位向上进,所以循环次数就多了。

那么什么时候结束循环呢?  就是没有进位的时候,不需要再加了。

为什么要有循环呢?  因为相加就会产生进位,进位了说明没算完,需要继续加上进位,知道没有进位。

题解来源

作者:jyd
链接:leetcode-cn.com/problems/bu… 来源:力扣(LeetCode)

方法二:奇思妙想解法

代码

真没有运算符!!

class Solution:
    def add(self, a: int, b: int) -> int:
        result = [a,b]
        return sum(result)

题解来源

作者:luyao777
链接:leetcode-cn.com/problems/bu… 来源:力扣(LeetCode)

来源

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/bu…