算法笔记 -- 67. 二进制求和

118 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

一、题目描述:

67. 二进制求和 - 力扣(LeetCode) (leetcode-cn.com)

给你两个二进制字符串,返回它们的和(用二进制表示)。

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

示例 1:

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

示例 2:

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

提示:

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

二、思路分析:

因为 js 的精度比较小,所以官方的模拟和位运算方法都不适合 js,数值较大时结果会出错。 又因为 js 的字符串的值不能改动,所以空间复杂度不可能为 o(1)。 用 res 栈保存结果,用 carry 代表进位,初始化为 0: 初始化 i = a.length-1, j = b.length-1 ,同时遍历 a 和 b 字符串:

  • 当 carry、a[i]、b[j]中只有 1 个 1 或均为 1 时,res 该位置为 1,即 carry ^ a[i] ^ b[j] 为 1;
  • 当 carry、a[i]、b[j]中有 2 个 1 或均为 0 时,res 该位置为 0,即 carry ^ a[i] ^ b[j] 为 0;
  • 当 carry、a[i]、b[j]中存在大于 2 个 1 时需要进位,即三者之和大于等于 2。 i < 0 或 j < 0 时跳出循环。

对多出来的那一部分进行遍历进位即可,假设 a 长度比较长:

  • a[i]、carry 异或结果就是 res 该位置的值;
  • a[i]、carry 与结果就是下一次进位的值。

三、AC 代码:

var addBinary = function(a, b) {
    let carry = 0;
    let res = [];
    let i = a.length-1, j = b.length-1;
    for(; i >= 0 && j >= 0; i--, j--) {
        res.unshift(carry ^ a[i] ^ b[j]);
        carry = (carry+parseInt(a[i])+parseInt(b[j])) >= 2 ? 1 : 0;
    }
    while(i >= 0) { 
        res.unshift(a[i] ^ carry); 
        carry = a[i] & carry;
        i--;
    }
    while(j >= 0) { 
        res.unshift(b[j] ^ carry); 
        carry = b[j] & carry;
        j--;
    }
    if(carry) { res.unshift(1); }
    return res.join("");
};

范文参考

C语言,模拟高精度加法【适用多种情况】 - 二进制求和 - 力扣(LeetCode)

Java解题:时间复杂度(max(a.length ,b.length)),空间复杂度(1) - 二进制求和 - 力扣(LeetCode)