二进制求和

标签: 位运算 数学 字符串 模拟

难度: Easy

给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。

输入为 非空 字符串且只包含数字 1 和 0

示例 1:

输入: a = "11", b = "10"
输出: "101"

示例 2:

输入: a = "1010", b = "1011"
输出: "10101"

提示:

  • 每个字符串仅由字符 '0''1' 组成。
  • 1 <= a.length, b.length <= 10^4
  • 字符串如果不是 "0" ,就都不含前导零。

注意:本题与主站 67 题相同:https://leetcode-cn.com/problems/add-binary/

Submission

运行时间: 24 ms

内存: 15.9 MB

class Solution:
    def addBinary(self, a, b) -> str:
        x, y = int(a, 2), int(b, 2)
        while y:
            answer = x ^ y
            carry = (x & y) << 1
            x, y = answer, carry
        return bin(x)[2:]

Explain

该题解使用了位运算来模拟二进制加法的过程。首先,将两个二进制字符串a和b转换成整数x和y。接着,使用while循环,循环条件为y不为0,即还有进位需要处理。在循环内部,使用XOR运算(x ^ y)来计算x和y的无进位和,并将其存储在变量answer中。接着,使用AND运算(x & y)并左移一位来计算进位,并存储在变量carry中。然后,将answer的值赋给x,carry的值赋给y,继续进行下一次循环。当y为0,即没有进位时,循环结束。最后,将x转换为二进制字符串并去掉前缀'0b',得到最终的结果。

时间复杂度: O(n)

空间复杂度: O(1)

# 定义解决问题的类
class Solution:
    def addBinary(self, a, b) -> str:
        # 将二进制字符串转换为整数
        x, y = int(a, 2), int(b, 2)
        # 当存在进位时继续处理
        while y:
            # 计算无进位和
            answer = x ^ y
            # 计算进位,注意左移
            carry = (x & y) << 1
            # 为下一轮迭代更新x和y
            x, y = answer, carry
        # 将最终的整数结果转换为二进制字符串并去掉前缀'0b'
        return bin(x)[2:]

Explore

将二进制字符串转换为整数可以利用计算机内建的整数处理能力,使得运算更加高效。整数类型具有固定的位数和已优化的位运算指令,可以更快地执行加法和位移操作。直接处理字符串需要手动管理每一位的进位和求和,代码会更加复杂且可能效率较低。

XOR运算(异或运算)的特点是,当两个输入位不同(即一个为1,一个为0)时,输出为1;如果两个输入位相同(都为0或都为1),输出为0。这恰好符合二进制加法中无进位求和的规则,即两位相加时,只有一个为1才会在该位产生1,两者都为1或都为0时在该位不产生1。因此,XOR运算能有效模拟无进位的二进制加法结果。

AND运算(与运算)的特点是只有两个输入位都为1时,输出才为1。在二进制加法中,两位都为1时会产生一个进位,这个进位应该加到下一更高位上。因此,我们需要将AND运算的结果(进位)左移一位,以确保这个进位被加到正确的位置上。这一步模拟的是在手工二进制加法中,每当两位相加产生进位时,该进位影响的是下一位的计算。