Adding Two Negabinary Numbers
Add base -2 numbers digit-by-digit — borrow propagates differently; trim leading zeros.
5 min read
math array
Problem#
Two numbers are given as digit arrays in base -2 (MSB first, digits 0/1). Return their sum in the same form.
Examples#
[1,1,1,1,1], [1,0,1]→[1,0,0,0,0](21 + (-3) = 18 = “10100” in base -2… wait — 11 + (-3) → 8).[1,1,1,1,1], [1,0,1]→[1,0,0,0,0].[1,0,1], [1]→[1,0,0].
Constraints#
1 <= arr1.length, arr2.length <= 1000.
Approach#
Walk from LSB. Sum is a + b + carry. In base -2, the digit at position i is s mod -2… but easier: use signed carry. After adding, if s >= 2, set digit to s - 2 and carry -1. If s < 0, set digit to s + 2 and carry +1. Trim leading zeros.
Solution#
class Solution {public: vector<int> addNegabinary(vector<int>& a, vector<int>& b) { vector<int> out; int i = a.size() - 1, j = b.size() - 1, carry = 0; while (i >= 0 || j >= 0 || carry) { int x = (i >= 0) ? a[i--] : 0; int y = (j >= 0) ? b[j--] : 0; int s = x + y + carry; if (s >= 2) { s -= 2; carry = -1; } else if (s < 0) { s += 2; carry = 1; } else carry = 0; out.push_back(s); } while (out.size() > 1 && out.back() == 0) out.pop_back(); reverse(out.begin(), out.end()); return out; }};func addNegabinary(a []int, b []int) []int { out := []int{} i, j, carry := len(a)-1, len(b)-1, 0 for i >= 0 || j >= 0 || carry != 0 { x, y := 0, 0 if i >= 0 { x = a[i] i-- } if j >= 0 { y = b[j] j-- } s := x + y + carry if s >= 2 { s -= 2 carry = -1 } else if s < 0 { s += 2 carry = 1 } else { carry = 0 } out = append(out, s) } for len(out) > 1 && out[len(out)-1] == 0 { out = out[:len(out)-1] } for l, r := 0, len(out)-1; l < r; l, r = l+1, r-1 { out[l], out[r] = out[r], out[l] } return out}from typing import List
class Solution: def addNegabinary(self, arr1: List[int], arr2: List[int]) -> List[int]: out: List[int] = [] i, j, carry = len(arr1) - 1, len(arr2) - 1, 0 while i >= 0 or j >= 0 or carry: x = arr1[i] if i >= 0 else 0 y = arr2[j] if j >= 0 else 0 s = x + y + carry if s >= 2: s -= 2 carry = -1 elif s < 0: s += 2 carry = 1 else: carry = 0 out.append(s) i -= 1 j -= 1 while len(out) > 1 and out[-1] == 0: out.pop() out.reverse() return outvar addNegabinary = function(arr1, arr2) { const out = []; let i = arr1.length - 1, j = arr2.length - 1, carry = 0; while (i >= 0 || j >= 0 || carry !== 0) { const x = i >= 0 ? arr1[i--] : 0; const y = j >= 0 ? arr2[j--] : 0; let s = x + y + carry; if (s >= 2) { s -= 2; carry = -1; } else if (s < 0) { s += 2; carry = 1; } else carry = 0; out.push(s); } while (out.length > 1 && out[out.length - 1] === 0) out.pop(); return out.reverse();};class Solution { public int[] addNegabinary(int[] arr1, int[] arr2) { List<Integer> out = new ArrayList<>(); int i = arr1.length - 1, j = arr2.length - 1, carry = 0; while (i >= 0 || j >= 0 || carry != 0) { int x = i >= 0 ? arr1[i--] : 0; int y = j >= 0 ? arr2[j--] : 0; int s = x + y + carry; if (s >= 2) { s -= 2; carry = -1; } else if (s < 0) { s += 2; carry = 1; } else carry = 0; out.add(s); } while (out.size() > 1 && out.get(out.size() - 1) == 0) { out.remove(out.size() - 1); } int n = out.size(); int[] ans = new int[n]; for (int k = 0; k < n; k++) ans[k] = out.get(n - 1 - k); return ans; }}function addNegabinary(arr1: number[], arr2: number[]): number[] { const out: number[] = []; let i = arr1.length - 1, j = arr2.length - 1, carry = 0; while (i >= 0 || j >= 0 || carry !== 0) { const x = i >= 0 ? arr1[i--] : 0; const y = j >= 0 ? arr2[j--] : 0; let s = x + y + carry; if (s >= 2) { s -= 2; carry = -1; } else if (s < 0) { s += 2; carry = 1; } else carry = 0; out.push(s); } while (out.length > 1 && out[out.length - 1] === 0) out.pop(); return out.reverse();}Editorial#
In base -2, weight of position i is (-2)^i. The carry going to the next-higher position is negated relative to standard binary — that’s why exceeding 2 produces a -1 carry and going negative produces a +1 carry. Both rules keep each digit in {0, 1}.
Complexity#
- Time:
O(m + n). - Space:
O(m + n).
Concept revision#
Related#