算法题详解:二进制之和(困难题55)| 豆包MarsCode AI刷题

55 阅读6分钟

问题描述

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

做题思路

1. 问题分析

  • 二进制字符串相加:我们需要将两个二进制字符串相加,得到一个新的二进制字符串。
  • 转换为十进制:将得到的二进制字符串转换为十进制数。

为了实现这个目标,我们可以分两步进行:

  1. 二进制字符串相加:从最低位开始逐位相加,处理进位。
  2. 二进制转十进制:将得到的二进制字符串转换为十进制数。

2. 关键点

  • 逐位相加:从最低位开始逐位相加,处理进位。
  • 字符串操作:使用 StringBuilder 来方便地处理字符串的反转和拼接。
  • 二进制转十进制:使用 Integer.parseInt 方法将二进制字符串转换为十进制数。

3. 解决方案

  1. 反转二进制字符串:为了从最低位开始处理,我们将两个二进制字符串反转。
  2. 逐位相加:从最低位开始逐位相加,处理进位,直到所有位都处理完并且没有进位为止。
  3. 结果反转:将得到的二进制结果字符串反转回正常顺序。
  4. 转换为十进制:使用 Integer.parseInt 方法将二进制字符串转换为十进制数。

做题方式

  1. 反转二进制字符串

    • 使用 StringBuilderreverse 方法将两个二进制字符串反转。
  2. 逐位相加

    • 初始化一个 StringBuilder 来存储结果。
    • 初始化一个进位变量 carry,初始值为0。
    • 遍历两个字符串的每一位,从最低位开始:
      • 获取当前位的数字,如果超出字符串长度则视为0。
      • 计算当前位的和以及新的进位。
      • 将当前位的结果追加到 StringBuilder 中。
  3. 结果反转

    • StringBuilder 中的结果字符串反转回正常顺序。
  4. 转换为十进制

    • 使用 Integer.parseInt 方法将二进制字符串转换为十进制数。

详细代码讲解

public class Main {
    public static String solution(String binary1, String binary2) {
        // 反转二进制字符串以便从最低位开始处理
        StringBuilder sb1 = new StringBuilder(binary1).reverse();
        StringBuilder sb2 = new StringBuilder(binary2).reverse();

        int maxLength = Math.max(sb1.length(), sb2.length());
        StringBuilder result = new StringBuilder();
        int carry = 0;

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

        // 将二进制结果转换为十进制
        return Integer.toString(Integer.parseInt(result.reverse().toString(), 2));
    }

    public static void main(String[] args) {
        // 测试用例
        System.out.println(solution("101", "110").equals("11")); // true
        System.out.println(solution("111111", "10100").equals("83")); // true
        System.out.println(solution("111010101001001011", "100010101001").equals("242420")); // true
        System.out.println(solution("111010101001011", "10010101001").equals("31220")); // true
        System.out.println(solution("11", "1").equals("4")); // true
    }
}

代码解析

  1. 方法定义

    • public static String solution(String binary1, String binary2):定义一个静态方法 solution,接收两个二进制字符串 binary1binary2,返回一个表示其十进制和的字符串。
  2. 反转二进制字符串

    • StringBuilder sb1 = new StringBuilder(binary1).reverse();:将 binary1 反转。
    • StringBuilder sb2 = new StringBuilder(binary2).reverse();:将 binary2 反转。
  3. 初始化变量

    • int maxLength = Math.max(sb1.length(), sb2.length());:获取两个字符串的最大长度。
    • StringBuilder result = new StringBuilder();:初始化一个 StringBuilder 来存储结果。
    • int carry = 0;:初始化进位变量 carry,初始值为0。
  4. 逐位相加

    • for (int i = 0; i < maxLength || carry != 0; i++) {:遍历两个字符串的每一位,直到所有位都处理完并且没有进位为止。
    • int bit1 = i < sb1.length() ? sb1.charAt(i) - '0' : 0;:获取 sb1 的当前位数字,如果超出长度则视为0。
    • int bit2 = i < sb2.length() ? sb2.charAt(i) - '0' : 0;:获取 sb2 的当前位数字,如果超出长度则视为0。
    • int sum = bit1 + bit2 + carry;:计算当前位的和。
    • result.append(sum % 2);:将当前位的结果追加到 result 中。
    • carry = sum / 2;:更新进位。
  5. 结果反转

    • result.reverse();:将 result 中的结果字符串反转回正常顺序。
  6. 转换为十进制

    • Integer.parseInt(result.toString(), 2);:将二进制字符串转换为十进制数。
    • Integer.toString(...);:将十进制数转换为字符串。
  7. 测试用例

    • System.out.println(solution("101", "110").equals("11"));:测试用例1,输出 true 表示结果正确。
    • System.out.println(solution("111111", "10100").equals("83"));:测试用例2,输出 true 表示结果正确。
    • System.out.println(solution("111010101001001011", "100010101001").equals("242420"));:测试用例3,输出 true 表示结果正确。
    • System.out.println(solution("111010101001011", "10010101001").equals("31220"));:测试用例4,输出 true 表示结果正确。
    • System.out.println(solution("11", "1").equals("4"));:测试用例5,输出 true 表示结果正确。

总结

通过使用字符串操作和逐位相加的方法,我们可以在 (O(n)) 时间复杂度内完成两个二进制字符串的相加,并将结果转换为十进制数。这种方法不仅高效,而且简洁,非常适合处理大数的二进制相加问题。

扩展思考

  1. 大数处理

    • 如果二进制字符串非常长,超过了 Integer 的范围,可以使用 BigInteger 类来处理大数。
    • BigInteger 类提供了大数的加法和二进制转换方法,可以轻松处理非常长的二进制字符串。
  2. 优化

    • 如果需要进一步优化性能,可以考虑使用更高效的字符串操作方法,或者使用位运算来处理二进制相加。
  3. 实际应用

    • 这种方法在数据处理和算法竞赛中非常常见,尤其是在需要高效处理二进制数据的情况下。
    • 例如,在密码学和数据压缩算法中,经常需要处理大数的二进制操作。