LeetCode: 371. 两整数之和

580 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第21天,点击查看活动详情

371. 两整数之和

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

给你两个整数 a 和 b ,不使用 运算符 + - ​​​​​​​,计算并返回两整数之和。

示例 1:

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

示例 2:

输入:a = 2, b = 3 输出:5

提示:

-1000 <= a, b <= 1000

解法

  • 循环: sum
class Solution:
    def getSum(self, a: int, b: int) -> int:
        return sum([a, b])
  • 位运算: 回顾一下二进制相关知识: 二进制就是将数字转换成二进制0,1的形式进行表示:
    • 原码:

      • 正数:按照绝对值大小转换成的二进制数
      • 负数: 按照绝对值大小转换成的二进制数,然后最高位补1,称为原码
    • 反码:

      • 正数:反码与原码相同
      • 负数:反码为对该数的原码除符号位外各位取反[每一位取反(除符号位)]
    • 补码:

      • 正数: 补码与原码相同
      • 负数:补码为对该数的原码除符号位外各位取反,然后在最后一位加1。另外负数的补码的补码就是原码
    • 二进制加减法: 计算机计算二进制加法是分三部,第一步为将两个加数转换为二进制数,计算两个加数不需要进位的和(利用异或运算 ^ ),得出的结果。第二部将两个加数进行与运算(&)。第三部利用与运算得到结果进行左移运算(<<)(同时为计算两个加数需要进位的和),得出结果。将或异运算的结果和左移运算的结果作为两个新的加数,重复此操作。直到当与运算的结果为0,则异或运算的结果则为两个加数的和所对应的二进制数。

在这里插入图片描述 注意: 二进制中减法是用补码的加法来实现的

在 Python 中,整数不是 32 位的,也就是说你一直循环左移并不会存在溢出的现象,这就需要我们手动对 Python 中的整数进行处理,手动模拟 32 位 INT 整型。

具体做法是将整数对 0x100000000(2^32) 取模,保证该数从 32 位开始到最高位都是 0

class Solution(object):
    def getSum(self, a, b):
        """
        :type a: int
        :type b: int
        :rtype: int
        """
        # 2^32
        MASK = 0x100000000
        # 整型最大值
        MAX_INT = 0x7FFFFFFF
        MIN_INT = MAX_INT + 1
        while b != 0:
            # 计算进位
            carry = (a & b) << 1 
            # 取余范围限制在 [0, 2^32-1] 范围内
            a = (a ^ b) % MASK
            b = carry % MASK
        return a if a <= MAX_INT else ~((a % MIN_INT) ^ MAX_INT)   # 如果不对负数特殊处理,那么负数的前32位是0,最后输出的是大于32位的正数

复杂度分析

最好的情况下

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

参考