LeetCode67、二进制求和

58 阅读1分钟

LeetCode 系列记录我学习算法的过程。

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

题目

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

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

示例:

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


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

提示

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

思路

这个题目也是涉及到进位的问题,可以使用双指针来对两个字符串进行遍历

将对应位的值相加后的值进位后并记录下来

  • 定义 p 记录当前项是否需要进位,x 遍历 ay 遍历 bres 存储结果
  • 从后往前对字符串 ab 进行遍历
  • 定义 n 记录当前两数组项与进位之和,并移动指针
  • 判断 n 是否大于 1,大于则需要进位,并将当前项赋值为减去 2 后的值并拼接在 res
  • 反之则无需进位,直接将 n 拼接到 res 即可
  • 最后遍历完再判断是否还有进位未处理,有则在数组开头插入 1
  • 将处理好后的 res 返回

代码实现

/**
 * @param {string} a
 * @param {string} b
 * @return {string}
 */
var addBinary = function(a, b) {
    let p = false, // 是否需要进位
        x = a.length - 1, // 指向 a 的指针
        y = b.length - 1, // 指向 b 的指针
        res = '' // 结果
    // 当 a 和 b 都遍历完则结束循环
    while(x >= 0 || y >= 0) {
        // n 记录当前两项之和
        let n = 0
        // 如果 a 当前项存在,则加上该值,并向前移动指针
        if (a[x]) {
            n += Number(a[x])
            x--
        }
        // b 同上
        if (b[y]) {
            n += Number(b[y])
            y--
        }
        // 如果当前存在进位,则加一
        if (p) n++
        // 当 n > 1 时需要进位,保留减 2 之后的值
        if (n > 1) {
            res = (n - 2) + res
            p = true
        } else {
            // 不需要进位则直接拼接
            res = n + res
            p = false
        }
    }
    // 最后还有进位则开头拼接 1
    if (p) res = '1' + res
    // 返回结果
    return res
};

image.png

优化

还可以将代码进行简化,不需要写太多的 if 判断,从后往前存储结果,最后将结果翻转返回即可

var addBinary = function(a, b) {
    let res = "", p = 0
    for(let i = a.length - 1, j = b.length - 1; i >= 0 || j >= 0; i--, j--) {
        let sum = p
        sum += i >= 0 ? parseInt(a[i]) : 0
        sum += j >= 0 ? parseInt(b[j]) : 0
        res += sum % 2
        p = Math.floor(sum / 2)
    }
    res += p == 1 ? p : ""
    // 翻转结果
    return res.split('').reverse().join('')
};

image.png