#67 数学模拟 简单

二进制求和

在 LeetCode 上查看 ↗

🎧 语音讲解

开车或通勤时可听,跟着思路走一遍

速度

📋 题目描述

给你两个二进制字符串 a 和 b,以二进制字符串的形式返回它们的和。

字符串仅由 '0' 或 '1' 组成;若不是 "0" 则不含前导零。

示例 1

输入:a = "11", b = "1"
输出:"100"

解释:3 + 1 = 4,二进制为 100。

示例 2

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

解释:10 + 11 = 21,二进制为 10101。

💭 模拟答题者思考

1. 暴力:把两个二进制串转成整数相加再转回二进制——Python 可用 bin(int(a,2)+int(b,2)),但长度可达 104,且面试要的是「模拟竖式」过程。

2. 重复在哪里?和十进制加法一样:从最低位(字符串末尾)对齐,每位只有 0/1,和为 0/1/2/3,当前位写下 sum % 2,进位 sum // 2。

3. 两串长度不同(如 "11" + "1")时,较短串左侧视为补 0,只需在指针走出边界后把该侧位当作 0。

4. 两串都扫完若 carry==1(如 "1"+"1"→"10"),结果比较长串多一位,不能忘记最高位的 1。

5. 从低位往高位收集字符,最后反转(或头插)才符合「无前导零」的输出习惯。

🧠 变量语义(先读这三句再编码)

变量类型语义(三句法)
carryint定义:当前列相加后向更高位传递的进位,取值 0 或 1,初始为 0
维护:每位处理完后,若 bit_a + bit_b + carry >= 2 则 carry=1 否则 carry=0
更新:从两串末尾同步向左扫描,用新 carry 进入下一列;两串都扫完后若 carry==1 再补一位
i / jint定义:a、b 当前正在处理的字符下标,分别从 len(a)-1、len(b)-1 开始
维护:某串已扫完时,该侧当前位视为 0(相当于前导补零对齐)
更新:每轮若 i>=0 则取 a[i] 并 i-=1,同理 j
ans(或逆序收集)str / list定义:从低位到高位依次得到的和位字符
维护:每列的和位为 (bit_a + bit_b + carry) % 2,追加到结果尾部(或先 push 再最后反转)
更新:循环结束后若仍有进位,再追加 '1',最后反转得到最高位在左的字符串

⌨️ 落码步骤

1. carry = 0,i = len(a)-1,j = len(b)-1,用列表 bits 收集结果位

2. 当 i >= 0 或 j >= 0 或 carry:取当前位 da = int(a[i]) if i>=0 else 0,db 同理;sum = da + db + carry

3. bits.append(str(sum % 2)),carry = sum // 2,i--,j--

4. 将 bits 反转拼接为字符串返回(或循环中用 result = str(sum%2) + result 正序构建)

💻 代码实现

class Solution:
    def addBinary(self, a: str, b: str) -> str:
        i, j = len(a) - 1, len(b) - 1
        carry = 0
        bits = []
        while i >= 0 or j >= 0 or carry:
            da = int(a[i]) if i >= 0 else 0
            db = int(b[j]) if j >= 0 else 0
            s = da + db + carry
            bits.append(str(s % 2))
            carry = s // 2
            i -= 1
            j -= 1
        return "".join(reversed(bits))
class Solution {
public:
    string addBinary(string a, string b) {
        int i = (int)a.size() - 1, j = (int)b.size() - 1;
        int carry = 0;
        string ans;
        while (i >= 0 || j >= 0 || carry) {
            int da = i >= 0 ? a[i--] - '0' : 0;
            int db = j >= 0 ? b[j--] - '0' : 0;
            int s = da + db + carry;
            ans.push_back(char('0' + s % 2));
            carry = s / 2;
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};
// 时间 O(max(m,n)),空间 O(max(m,n))

📈 复杂度分析

时间复杂度 O(max(m,n))
空间复杂度 O(max(m,n))(结果字符串)

⚠️ 常见坑

❗ 从字符串头部开始加:低位在末尾,必须从 len-1 向 0 扫描。

❗ 忘记最终进位:"1"+"1" 循环结束后 carry==1,需再写入一位 '1'。

❗ C++ 中 char + char 是 ASCII 相加,应写成 a[i]-'0' 得到 0/1。

🔍 必测边界 Case

Case 1:长度不等
"11" + "1" → "100"(较短串左侧补 0)
Case 2:等长全进位
"1111" + "1" → "10000"(结果位数 +1)
Case 3:单比特
"0" + "0" → "0","1" + "0" → "1"
Case 4:较长串
"1010" + "1011" → "10101"(示例 2)
Case 5:仅进位传播
"111" + "111" → "1110"(每位都产生进位)