LeetCode 67题 二进制求和 -- JavaScript

题目描述:

给定两个二进制字符串,返回他们的和(用二进制表示)。输入为非空字符串且只包含数字 1 和 0.

示例 :

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

方法分析: 

该题和第66题一样,粗略一看让人觉得很简单,很容易考虑不全面而导致踩坑。本人的踩坑代码如下:

var addBinary = function(a, b) {
  return (parseInt(a,2) + parseInt(b,2)).toString(2);
};

在一般情况下,即a和b的十进制数在 2^{53} 以下,都不会有问题;但是一旦超过该范围,就会产生计算失真。

参考我关于LeetCode第66题的分析:https://blog.csdn.net/qq_30216191/article/details/81488542

所以,我们又只有另寻它法了。

代码实现:

var addBinary = function(a, b) {
  //将计算位左对齐
  var [a2Arr, b2Arr] = [a.split("").reverse(), b.split("").reverse()];
  //定义进位 carry 
  var [lena, lenb, carry, result] = [a.length, b.length, 0, []];
  //取得较长数组进行遍历,以确保完全迭代
  var lenMax = Math.max(lena,lenb);
  for (var i = 0; i < lenMax; i++) {
      //每一项的值为两数组对应项数字和加上进位值
      //括号前面的加号代表类型转换,转换不了就置0
      var itemSum = +(a2Arr[i] || 0) + +(b2Arr[i] || 0) + carry;
      //根据每项值来定义结果位和进位
      if(itemSum == 0){
          result[i] = 0;
          carry = 0;
      }else if(itemSum == 1){
          result[i] = 1;
          carry = 0;
      }else if(itemSum == 2){
          result[i] = 0;
          carry = 1;
      }else{
          result[i] = 1;
          carry = 1;
      }
  }
  //若最高位发生进位,插入1
  if (carry == 1) result.push(1);
  //反序并连接为字符串
  return result.reverse().join("");
};

代码解析:

因为我个人觉得左对齐对计算更方便,所以我将输入字符串转变为了数组并反序排序,这样就是左对齐的了。然后定义了进位 carry ,其在计算中起着进位的作用。我们将遍历长度最长的数组(lenMax),以确保完全迭代。其中每一项的和都由两个数组对应位的数值加上进位值。加号“+”除了可以作为运算符,还起着类型转换的作用,其将字符串类型转换为数字类型;当无法转换时,以0代替。然后我们根据每项的和,确定结果中该位的值。

  1. 和为0,结果中该位为0,未发生进位,carry为0,
  2. 和为1,结果中该位为1,未发生进位,carry为0,
  3. 和为2,结果中该位为0,因为二进制1+1=0(去掉了进位1),,发生了进位,carry为1,
  4. 和为其他(3),结果中该位为1,因为二进制1+1+1=1(去掉了进位1),发生了进位,carry为1

如果当迭代完,进位carry仍然为1,此时,在数组末尾添加1作为最高位。最后,将结果反序并组合为字符串输出即可。

该算法的时间复杂度为:O(n) 

该算法的空间复杂度为:O(n) 

相关链接:https://leetcode-cn.com/problems/add-binary/description/

你可能感兴趣的:(LeetCode)