青训营刷题-8

184 阅读4分钟

8 二进制之和

给定两个二进制字符串,返回他们的和(用十进制字符串表示)。输入为非空字符串且只包含数字 1 和 0 ,请考虑大数问题。时间复杂度不要超过 O(n^2),其中 n 是二进制的最大长度。

输入格式

每个样例只有一行,两个二进制字符串以英文逗号“,”分割

输出格式

输出十进制格式的两个二进制的和

输入样例

101,110

输出样例

11

数据范围

每个二进制不超过 100 个字符,JavaScript 语言下请考虑大数的情况。

解题思路

1. 二进制转十进制

由于二进制字符串长度可能达到 100 位,直接转换为整数类型(如 intlong)可能会导致溢出。因此,需要使用字符串来模拟二进制到十进制的转换过程。

转换方法
  • 初始化:将十进制结果初始化为字符串 "0"

  • 逐位处理:从二进制字符串的最高位(左侧)开始,依次处理每一位:

    1. 乘以2:将当前的十进制字符串乘以 2。这是因为二进制的每一位代表 2 的幂次。
    2. 加1(如果当前位为1) :如果当前处理的二进制位是 '1',则在乘以 2 的结果上加 1

通过这种方式,逐位累加,最终得到完整的十进制字符串表示。

示例
  • 二进制字符串 101

    • 初始十进制字符串:"0"

    • 处理第1位 '1'

      • 乘以2:0 * 2 = 0
      • 加1:0 + 1 = 1
      • 十进制字符串更新为 "1"
    • 处理第2位 '0'

      • 乘以2:1 * 2 = 2
      • 加0:2 + 0 = 2
      • 十进制字符串更新为 "2"
    • 处理第3位 '1'

      • 乘以2:2 * 2 = 4
      • 加1:4 + 1 = 5
      • 十进制字符串更新为 "5"
    • 最终十进制结果"5"

2. 十进制字符串相加

转换得到两个十进制字符串后,需要将它们相加得到最终的十进制和。由于这两个字符串可能非常长(大于常规数据类型的范围),同样需要使用字符串模拟手动加法。

加法方法
  • 从右到左遍历:同时从两个十进制字符串的末尾(最低位)开始,逐位相加。

  • 处理进位

    • 每一位相加的结果如果大于或等于 10,则需要进位到更高位。
  • 构建结果字符串:将每一位的和(考虑进位)添加到结果字符串的前端。

  • 最终结果:遍历完成后,结果字符串即为两数之和的十进制表示。

示例
  • 十进制字符串 "5""6"

    • 从右到左:

      • 5 + 6 = 11
      • 记录个位数 1,进位 1
    • 由于已经遍历完所有位,且有进位 1,将其添加到结果前端。

    • 最终结果"11"

3. 整体流程总结

  1. 输入解析:分割输入,获取两个二进制字符串。
  2. 二进制转十进制:将每个二进制字符串转换为对应的十进制字符串。
  3. 十进制相加:将两个十进制字符串相加,得到最终的十进制和。
  4. 输出结果:返回最终的十进制字符串作为结果。

算法实现

public class Main {
    public static String solution(String binary1, String binary2) {
        // Please write your code here
        // 将两个二进制字符串转换为十进制字符串
        String dec1 = binaryToDecimal(binary1);
        String dec2 = binaryToDecimal(binary2);
        
        // 将两个十进制字符串相加
        String decimalSum = addStrings(dec1, dec2);
        
        return decimalSum;
    }
    private static String binaryToDecimal(String bin) {
        String decimal = "0";
        for(int i = 0; i < bin.length(); i++) {
            char c = bin.charAt(i);
            // 将当前十进制数乘以2
            decimal = multiplyByTwo(decimal);
            // 如果当前二进制位为'1',则加1
            if(c == '1') {
                decimal = addOne(decimal);
            }
        }
        return decimal;
    }

    private static String addOne(String num) {
        StringBuilder sb = new StringBuilder();
        int carry = 1; // 初始进位为1,因为是加1
        // 从右到左遍历字符串
        for(int i = num.length() - 1; i >= 0; i--) {
            int digit = num.charAt(i) - '0';
            int temp = digit + carry;
            carry = temp / 10;
            sb.append(temp % 10);
        }
        if(carry != 0) {
            sb.append(carry);
        }
        // 反转字符串
        return sb.reverse().toString();
    }
    
    private static String multiplyByTwo(String num) {
        StringBuilder sb = new StringBuilder();
        int carry = 0;
        // 从右到左遍历字符串
        for(int i = num.length() - 1; i >= 0; i--) {
            int digit = num.charAt(i) - '0';
            int temp = digit * 2 + carry;
            carry = temp / 10;
            sb.append(temp % 10);
        }
        if(carry != 0) {
            sb.append(carry);
        }
        // 反转字符串
        return sb.reverse().toString();
    }
    
    private static String addStrings(String num1, String num2) {
        StringBuilder sb = new StringBuilder();
        int carry = 0;
        int i = num1.length() - 1;
        int j = num2.length() - 1;
        // 从右到左遍历两个字符串
        while(i >= 0 || j >= 0 || carry != 0) {
            int digit1 = (i >= 0) ? (num1.charAt(i) - '0') : 0;
            int digit2 = (j >= 0) ? (num2.charAt(j) - '0') : 0;
            int sum = digit1 + digit2 + carry;
            carry = sum / 10;
            sb.append(sum % 10);
            i--;
            j--;
        }
        // 反转字符串
        return sb.reverse().toString();
    }
    

    public static void main(String[] args) {
        // You can add more test cases here
        System.out.println(solution("101", "110").equals("11"));
        System.out.println(solution("111111", "10100").equals("83"));
        System.out.println(solution("111010101001001011", "100010101001").equals("242420"));
        System.out.println(solution("111010101001011", "10010101001").equals("31220"));
    }
}