[剑指Offer]面试题65:用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
示例
输入: a = 1, b = 1
输出: 2
提示
a, b 均可能是负数或 0
结果不会溢出 32 位整数
思路

  • 和题目64类似,不能使用四则运算,自然就想到了位运算,即实现二进制的加法运算,学过计算机组成与结构的应该很容易理解。
  • 对于二进制加法来说,首先个位的2个数字相加,得到了一个和,一个进位,然后再计算十位,直到进位为0,加法结束。
  • 首先,求和,两个数字相加时和异或运算相同
  • 齐词,得到进位,二进制只有1+1会产生进位,因此,可以将两个数字做位与运算,然后左移
  • 最后,重复前两步,直到不再产生进位

题目中说明a,b可能是负数,而且结果不会超过32位,因此,需要知道python中的负数编码。
Python 负数的存储
Python/Java 中的数字都是以补码形式存储的。但Python没有int, long等不同长度变量,即没有变量位数的概念。
获取负数的补码:需要将数字与十六进制数0xffffffff相与。可理解为舍去此数字32位以上的数字,从无限长度变为一个32位整数。
返回前数字还原:若补码aa为负数(0x7fffffff是最大的正数的补码),需执行~(a^x) 操作,将补码还原至Python的存储格式。a^x运算将1至32位按位取反;~运算是将整个数字取反;因此,~(a^x)是将32位以上的位取反,即由0变为1,1至32位不变。
代码

# LeetCode
# 常规解法
class Solution:
    def add(self, a: int, b: int) -> int:
        x = 0xffffffff
        a, b = a & x, b & x
        while b != 0:
            a, b = (a ^ b), (a & b) << 1 & x
        return a if a <= 0x7fffffff else ~(a ^ x)
# 非常规解法
class Solution:
    def add(self, a: int, b: int) -> int:
       return sum([a,b])

参考:
https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/solution/mian-shi-ti-65-bu-yong-jia-jian-cheng-chu-zuo-ji-7/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章