Go&Java算法之二进制求和

105 阅读1分钟

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

二进制求和

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

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

 

  • 示例 1:

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

输出: "100"

  • 示例 2:

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

输出: "10101"  

提示:

每个字符串仅由字符 '0' 或 '1' 组成。

1 <= a.length, b.length <= 10^4

字符串如果不是 "0" ,就都不含前导零。

方法一:模拟法(Java)

我们可以借鉴列竖式的方法,末尾对齐,逐位相加。在十进制的计算中逢十进一,二进制中我们需要逢二进一。

注意,为了让各个位置对齐,你可以先反转这个代表二进制数字的字符串,然后低下标对应低位,高下标对应高位。

当然你也可以直接把 a 和 b 中短的那一个补 0 直到和长的那个一样长,然后从高位向低位遍历,对应位置的答案按照顺序存入答案字符串内,最终将答案串反转。

class Solution {
    public String addBinary(String a, String b) {
        StringBuffer ans = new StringBuffer();

        int n = Math.max(a.length(), b.length()), carry = 0;
        for (int i = 0; i < n; ++i) {
            carry += i < a.length() ? (a.charAt(a.length() - 1 - i) - '0') : 0;
            carry += i < b.length() ? (b.charAt(b.length() - 1 - i) - '0') : 0;
            ans.append((char) (carry % 2 + '0'));
            carry /= 2;
        }

        if (carry > 0) {
            ans.append('1');
        }
        ans.reverse();

        return ans.toString();
    }
}

时间复杂度:O(N)

空间复杂度:O(1)

方法二:模拟(Go)

具体方法已经在上文中表述,详情请看上文。

主要是需要先补零,保证长度一致,再采用逢二进一的思路,就好了!注意运行到最后一次,判断是否需要进位!即可

func addBinary(a string, b string) string {
    res := ""
    carry := 0
    l1, l2 := len(a) - 1, len(b) - 1
    for l1 >= 0 || l2 >= 0 {
        x, y := 0, 0
        if l1 >= 0 {
            x = int(a[l1] - byte('0'))
        }
        if l2 >= 0 {
            y = int(b[l2] - byte('0'))
        }

        sum := x + y + carry
        res += strconv.Itoa(sum % 2)
        carry = sum / 2

        l1--
        l2--
    }
    if carry != 0 {
        res += strconv.Itoa(carry)
    }

    return reverseString(res)
}

func reverseString(str string) string {
    temp := []byte(str)
    left, right := 0, len(temp) - 1
    for left < right {
        temp[left], temp[right] = temp[right], temp[left]
        left++
        right--
    }
    return string(temp)
}

时间复杂度:O(N)

空间复杂度:O(1)