青训营X豆包MarsCode技术训练营 | 豆包MarsCode AI刷题

63 阅读4分钟

二进制之和【难】

问题描述

小U和小R喜欢探索二进制数字的奥秘。他们想找到一个方法,将两个二进制字符串相加并以十进制的形式呈现。这个过程需要注意的是,他们的二进制串可能非常长,所以常规的方法可能无法处理大数。小U和小R希望你帮助他们设计一个算法,该算法能在保证时间复杂度不超过O(n^2)的前提下,返回两个二进制字符串的十进制求和结果。

测试样例

样例1:

输入:binary1 = "101" ,binary2 = "110"
输出:'11'

样例2:

输入:binary1 = "111111" ,binary2 = "10100"
输出:'83'

样例3:

输入:binary1 = "111010101001001011" ,binary2 = "100010101001"
输出:'242420'

样例4:

输入:binay1 = "111010101001011" ,binary2 = "10010101001"
输出:'31220'

样例5:

输入:binary1 = "11" ,binary2 = "1"
输出:'4'

怎么说,我感觉,应该算不上等级【难】,可能是因为我用库方法完成的,不是自己写板子吧🤔。

我这里,直接使用StringBuilder的字符串反转函数reverse、BigInteger的二进制字符串转十进制的函数,这应该不算投机取巧吧,不知道这里评定【难】是想着不要使用现成库函数,自己写板子完成这题吗😢

但是,自己写板子也可以,让我想到了之前刷C++题目时候,处理大整数‘加减乘除’,也是类似的做法,自己构建结构体、写板子函数😭。感觉就是‘字符串’+‘模拟’。 这里就提供一下刷题的链接吧:

P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态

P1303 A*B Problem - 洛谷 | 计算机科学教育新生态

扯远了,回归正题,要解决这个问题,需要将两个二进制字符串相加,并将结果转换为十进制数。可以手动实现二进制加法,然后将结果转换为十进制数。这样可以确保时间复杂度不超过 O(n^2)。

解题

具体步骤:

  1. 反转二进制字符串:为了方便从最低位到最高位进行加法运算,先将二进制字符串反转,使用 StringBuilder 反转二进制字符串。
StringBuilder sb1 = new StringBuilder(binary1).reverse();
StringBuilder sb2 = new StringBuilder(binary2).reverse();
  1. 逐位相加:从最低位开始逐位相加,同时处理进位。
for (int i = 0; i < maxLength || carry != 0; i++) {
    int bit1 = i < sb1.length() ? sb1.charAt(i) - '0' : 0;
    int bit2 = i < sb2.length() ? sb2.charAt(i) - '0' : 0;
    int sum = bit1 + bit2 + carry;
    result.append(sum % 2);
    carry = sum / 2;
}
  1. 处理剩余的进位:如果最后还有进位,则需要在结果中添加一个 '1'。
if (carry != 0) {
    result.append(carry);
}
  1. 将结果转换为十进制:使用 BigInteger 将二进制字符串转换为十进制数。 使用 BigInteger 将二进制字符串转换为十进制数并返回。
BigInteger decimalResult = new BigInteger(result.toString(), 2);
return decimalResult.toString();

完整代码

import java.math.BigInteger;

public class Main {
    public static String solution(String binary1, String binary2) {
        // 反转二进制字符串 方便从最低位到最高位进行加法运算
        StringBuilder sb1 = new StringBuilder(binary1).reverse();
        StringBuilder sb2 = new StringBuilder(binary2).reverse();

        // 初始化结果字符串和进位
        StringBuilder res = new StringBuilder(); // 结果
        int carry = 0; // 进位
        int maxLen = Math.max(sb1.length(), sb2.length());

        // 逐位相加 从最低位开始逐位相加,同时处理进位
        for (int i = 0; i < maxLen; i++) {
            // 获取两个二进制数的二进制位
            int bit1 = i < sb1.length() ? sb1.charAt(i) - '0' : 0;
            int bit2 = i < sb2.length() ? sb2.charAt(i) - '0' : 0;
            int sum = bit1 + bit2 + carry;
            res.append(sum % 2); // 获取加和后该位的数值
            carry = sum / 2; // 获取加和后的进位
        }

        // 如果最后还有进位
        if (carry != 0) {
            res.append(carry);
        }

        // 反转结果字符串
        res.reverse();

        // 将二进制结果转成十进制
        BigInteger decimalRes = new BigInteger(res.toString(), 2);

        return decimalRes.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"));
    }
}