📘 題目敘述
給你兩個二進位字串 a 和 b,請回傳它們的和(也是二進位字串)。
條件限制
1 <= a.length, b.length <= 10a和b只包含字元'0'或'1'- 每個字串都不包含前導零,除非該字串本身就是
"0"
🧠 解題思路
我這份寫法的核心就是「模擬二進位加法」。
因為二進位相加本來就會從最低位開始算,所以我先把 a、b 反轉,讓 index 0 變成最低位,接著一路往右掃,用 carry 記錄進位。
另外我先確保 a 是比較短的那個(如果 a 比 b 長就交換),這樣在迴圈裡判斷「i < m」就能知道 a 這位還存不存在。
最後我把算出來的結果也是反著加進 ans,所以結束後再把 ans 反轉回正確順序。
所有變數
m:a的長度(保證是較短的那個)n:b的長度(較長或相等)ans:答案字串(先用反向順序累積,最後再 reverse)carry:進位(只能是 0 或 1)digits:當前位元相加後的結果(包含進位),再轉成該位輸出與新的進位
🪜 主要流程步驟
1. 先確保 a 是比較短的字串
如果 a.size() > b.size(),就直接呼叫 addBinary(b, a) 交換,讓後面的邏輯只要處理「a 可能比 b 短」這一種情況。
2. 反轉兩個字串,從最低位開始加
把 a、b reverse 之後:
a[0]/b[0]就代表最低位- 我用
carry來記錄上一位加法產生的進位
3. 逐位相加,維護 carry,並把結果塞進 ans
我用 i = 0..n-1 掃過較長的 b:
- 先讓
digits = carry,並把carry歸零(等一下重新算) - 如果
i < m,代表a這位存在,就把a[i]和b[i]的 bit 都加進digits - 否則只有
b[i]需要加進來 - 若
digits > 1,代表需要進位:digits -= 2carry = 1
- 把
digits用to_string加到ans(此時ans是反向累積)
4. 迴圈結束後,如果還有進位就補上
如果最後 carry > 0,代表最高位還多一個 1,需要把它加進 ans。
5. 把 ans 反轉回正確方向
因為 ans 是從低位到高位一路 append,所以最後 reverse 回來才是正確答案。
⏱️ 複雜度
- 時間複雜度:
O(n),n = max(a.length, b.length)(反轉 + 一次掃描) - 空間複雜度:
O(n),答案字串需要長度約n(可能再多 1 位進位)
💻 程式碼實作
class Solution {
public:
string addBinary(string a, string b) {
if (a.size() > b.size()) { // a小b大
return addBinary(b, a);
}
int m = a.size(), n = b.size();
string ans = "";
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int carry = 0;
for (int i = 0; i < n; i++) {
int digits = carry;
carry = 0;
if (i < m) {
digits = digits + (a[i] - '0') + (b[i] - '0');
} else {
digits += (b[i] - '0');
}
if (digits > 1) {
digits -= 2;
carry = 1;
}
ans += to_string(digits);
}
if (carry > 0) {
ans += to_string(carry);
}
reverse(ans.begin(), ans.end());
return ans;
}
};