二进制之和解析 | 豆包MarsCode AI刷题

114 阅读5分钟

题目解析:二进制字符串相加并转换为十进制

1. 题目背景与问题理解

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

2. 问题分析

2.1 输入与输出
  • 输入:两个二进制字符串 binary1binary2
  • 输出:一个十进制字符串,表示两个二进制字符串相加的结果。
2.2 关键点
  • 大数问题:由于二进制字符串可能非常长,直接将它们转换为整数进行计算可能会导致溢出。因此,我们需要使用字符串来处理这些大数。
  • 时间复杂度:算法的时间复杂度应不超过 O(n^2),其中 n 是二进制字符串的长度。

3. 解题思路

3.1 对齐二进制字符串

由于两个二进制字符串的长度可能不同,我们需要在较短的字符串前面补0,使得两个字符串长度相同。这样可以方便我们逐位相加。

3.2 逐位相加

从最低位(字符串的最后一位)开始,逐位相加,并记录进位。每一位的相加结果可以通过以下公式计算: textsum=textbit1+textbit2+textcarrytext_{sum} = text_{bit1} + text_{bit2} + text_{carry}。 其中,bit1bit2 分别是当前位的二进制数字,carry 是前一位的进位。

3.3 处理进位

在每一位相加时,需要考虑前一位的进位。如果当前位的和大于1,则会产生进位。

3.4 生成结果字符串

将每一位的结果和进位组合成最终的二进制字符串。由于我们从最低位开始相加,最终的结果字符串需要反转。

3.5 转换为十进制

将最终的二进制字符串转换为十进制字符串。可以使用 BigInteger 类来处理大数问题。

4. 示例解法

4.1 对齐二进制字符串

假设 binary1 = "101"binary2 = "110"

  • 对齐后:binary1 = "101"binary2 = "011"
4.2 逐位相加

从最低位开始逐位相加:

  • 第1位:1 + 1 + 0 = 2,结果为 0,进位为 1
  • 第2位:0 + 1 + 1 = 2,结果为 0,进位为 1
  • 第3位:1 + 0 + 1 = 2,结果为 0,进位为 1

最终结果为 000,进位为 1,所以最终结果为 1000

4.3 转换为十进制

1000 转换为十进制:

  • 1000 对应的十进制为 8

5. 代码详解

import java.math.BigInteger;

public class Main {
    public static String solution(String binary1, String binary2) {
        // 对齐二进制字符串
        int maxLength = Math.max(binary1.length(), binary2.length());
        binary1 = String.format("%" + maxLength + "s", binary1).replace(' ', '0');
        binary2 = String.format("%" + maxLength + "s", binary2).replace(' ', '0');

        StringBuilder result = new StringBuilder();
        int carry = 0;

        // 逐位相加
        for (int i = maxLength - 1; i >= 0; i--) {
            int bit1 = binary1.charAt(i) - '0';
            int bit2 = binary2.charAt(i) - '0';
            int sum = bit1 + bit2 + carry;

            // 计算当前位的结果和进位
            result.append(sum % 2);
            carry = sum / 2;
        }

        // 处理最后的进位
        if (carry != 0) {
            result.append(carry);
        }

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

        // 将二进制字符串转换为十进制字符串
        return new BigInteger(result.toString(), 2).toString(10);
    }

    public static void main(String[] args) {
        // 测试用例
        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"));
    }
}
5.1 对齐二进制字符串
int maxLength = Math.max(binary1.length(), binary2.length());
binary1 = String.format("%" + maxLength + "s", binary1).replace(' ', '0');
binary2 = String.format("%" + maxLength + "s", binary2).replace(' ', '0');
  • 使用 Math.max 找到两个字符串的最大长度。
  • 使用 String.format 在较短的字符串前面补0,使得两个字符串长度相同。
5.2 逐位相加
for (int i = maxLength - 1; i >= 0; i--) {
    int bit1 = binary1.charAt(i) - '0';
    int bit2 = binary2.charAt(i) - '0';
    int sum = bit1 + bit2 + carry;

    // 计算当前位的结果和进位
    result.append(sum % 2);
    carry = sum / 2;
}
  • 从最低位开始逐位相加,并记录进位。
  • 使用 charAt 获取当前位的二进制数字,并将其转换为整数。
  • 计算当前位的和,并更新进位。
5.3 处理进位
if (carry != 0) {
    result.append(carry);
}
  • 如果最后一位相加后仍有进位,将其添加到结果字符串中。
5.4 生成结果字符串
result.reverse();
  • 由于我们从最低位开始相加,最终的结果字符串需要反转。
5.5 转换为十进制
return new BigInteger(result.toString(), 2).toString(10);
  • 使用 BigInteger 类将二进制字符串转换为十进制字符串。

6 总结

该算法通过逐位相加两个二进制字符串并处理进位,最终将结果转换为十进制字符串。时间复杂度为 O(n),其中 n 是二进制字符串的最大长度,主要消耗在逐位相加和字符串反转操作上。空间复杂度为 O(n),用于存储对齐后的二进制字符串和结果字符串。使用 BigInteger 类处理大数转换,确保了算法的稳定性和正确性。整体上,该算法高效且适用于处理大数问题。