leetcode力扣-剑指offer刷题-day2-002. 二进制加法

剑指 Offer II 002. 二进制加法 - 力扣(LeetCode) (leetcode-cn.com)https://leetcode-cn.com/problems/JFETK5/

给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。

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

示例 1:

输入: a = "11", b = "10"
输出: "101"
示例 2:

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

提示:

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

下手有点太急了没有考虑充分,想直接通过char做转化,但是这样暴力拆实在是太复杂了,虽然可以实现,但是复杂度太差。

写的时候发现好多东西都忘掉了,需要帮助回忆。Java String 类 | 菜鸟教程 (runoob.com)https://www.runoob.com/java/java-string.html 


class Solution {
    public String addBinary(String a, String b) {
        int length=0;
        int index=0;
        int lList=0;
        int isALarger=0;
        if(a.length()>b.length()){
            length=b.length();
            lList=a.length()+1;
            isALarger=1;
        }else{
            length=a.length();
            lList=b.length()+1;
        }
        char []result=new char[lList];
        String reverseA = new StringBuffer(a).reverse().toString();
        String reverseB = new StringBuffer(b).reverse().toString();

        for(int i=0;i

 leetcode力扣-剑指offer刷题-day2-002. 二进制加法_第1张图片


看一看官方的解答。

考虑一个最朴素的方法:先将 aa 和 bb 转化成十进制数,求和后再转化为二进制数。利用 Python 和 Java 自带的高精度运算,我们可以很简单地写出这个程序:

class Solution {
    public String addBinary(String a, String b) {
        return Integer.toBinaryString(
            Integer.parseInt(a, 2) + Integer.parseInt(b, 2)
        );
    }
}
如果 aa 的位数是 nn,bb 的位数为 mm,这个算法的渐进时间复杂度为 O(n + m)O(n+m)。但是这里非常简单的实现基于 Python 和 Java 本身的高精度功能,在其他的语言中可能并不适用,并且在 Java 中:

如果字符串超过 3333 位,不能转化为 Integer
如果字符串超过 6565 位,不能转化为 Long
如果字符串超过 500000001500000001 位,不能转化为 BigInteger
因此,为了适用于长度较大的字符串计算,我们应该使用更加健壮的算法。

方法一:模拟
思路和算法

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

具体的,我们可以取 n = \max\{ |a|, |b| \}n=max{∣a∣,∣b∣},循环 nn 次,从最低位开始遍历。我们使用一个变量 \textit{carry}carry 表示上一个位置的进位,初始值为 00。记当前位置对其的两个位为 a_ia i和 b_ib i,则每一位的答案为 (\textit{carry} + a_i + b_i) \bmod{2}(carry+a i+bi)mod2,下一位的进位为 \lfloor \frac{\textit{carry} + a_i + b_i}{2} \rfloor⌊ 2carry+ai+bi ⌋。重复上述步骤,直到数字 aa 和 bb 的每一位计算完毕。最后如果 \textit{carry}carry 的最高位不为 00,则将最高位添加到计算结果的末尾。

注意,为了让各个位置对齐,你可以先反转这个代表二进制数字的字符串,然后低下标对应低位,高下标对应高位。当然你也可以直接把 aa 和 bb 中短的那一个补 00 直到和长的那个一样长,然后从高位向低位遍历,对应位置的答案按照顺序存入答案字符串内,最终将答案串反转。这里的代码给出第一种的实现。

在这里思路是类似的,但是我自己写的显然更麻烦。其根本在于对java语言的掌握还不够熟练。

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();
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/JFETK5/solution/er-jin-zhi-jia-fa-by-leetcode-solution-fa6t/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 如果不允许使用加减乘除,则可以使用位运算替代上述运算中的一些加减乘除的操作。

我们可以设计这样的算法来计算:

把 aa 和 bb 转换成整型数字 xx 和 yy,在接下来的过程中,xx 保存结果,yy 保存进位。
当进位不为 00 时
计算当前 xx 和 yy 的无进位相加结果:answer = x ^ y
计算当前 xx 和 yy 的进位:carry = (x & y) << 1
完成本次循环,更新 x = answer,y = carry
返回 xx 的二进制形式
为什么这个方法是可行的呢?在第一轮计算中,answer 的最后一位是 xx 和 yy 相加之后的结果,carry 的倒数第二位是 xx 和 yy 最后一位相加的进位。接着每一轮中,由于 carry 是由 xx 和 yy 按位与并且左移得到的,那么最后会补零,所以在下面计算的过程中后面的数位不受影响,而每一轮都可以得到一个低 ii 位的答案和它向低 i + 1i+1 位的进位,也就模拟了加法的过程。

你可能感兴趣的:(leetcode,算法)