豆包MarsCode AI刷题(五)

61 阅读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:

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

样例5:

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

解决方案

问题理解

我们需要将两个二进制字符串相加,并将结果以十进制的形式返回。由于二进制字符串可能非常长,常规的整数类型可能无法处理,因此我们需要设计一个算法来处理大数。

数据结构选择

由于我们处理的是字符串形式的二进制数,我们可以直接使用字符串来存储和操作这些二进制数。

算法步骤

  1. 补齐长度:首先,我们需要确保两个二进制字符串的长度相同。如果长度不同,可以在较短的字符串前面补零。
  2. 逐位相加:从最低位(字符串的最后一位)开始,逐位相加,并记录进位。
  3. 处理进位:在逐位相加的过程中,如果某一位的和大于1,则需要进位。
  4. 生成结果:将逐位相加的结果拼接成一个新的二进制字符串。
  5. 转换为十进制:最后,将二进制字符串转换为十进制字符串。
public class Main {
    public static String solution(String binary1, String binary2) {
        // Step 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');

        // Step 2: 逐位相加
        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;

            // 处理进位
            carry = sum / 2;
            result.append(sum % 2);
        }

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

        // Step 3: 生成结果
        String binaryResult = result.reverse().toString();

        // Step 4: 转换为十进制
        // 使用Java的内置方法将二进制字符串转换为十进制字符串
        String decimalResult = new BigInteger(binaryResult, 2).toString(10);

        return decimalResult; // 返回十进制结果
    }

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

复杂度分析

时间复杂度

  1. 补齐长度

    • Math.max(binary1.length(), binary2.length()) 的时间复杂度是 O(1)
    • String.format 和 replace 操作的时间复杂度是 O(n),其中 n 是字符串的长度。
  2. 逐位相加

    • 逐位相加的循环次数是 maxLength,即 O(n),其中 n 是两个字符串中较长的那个的长度。
    • 每次循环中的操作(如 charAt- '0'+/%)都是 O(1) 的操作。
  3. 处理最后的进位

    • 这个操作的时间复杂度是 O(1)
  4. 生成结果

    • result.reverse() 的时间复杂度是 O(n)
    • toString() 的时间复杂度是 O(n)
  5. 转换为十进制

    • new BigInteger(binaryResult, 2) 的时间复杂度是 O(n)
    • toString(10) 的时间复杂度是 O(n)

综合以上分析,主要的时间复杂度来自于逐位相加和字符串操作,总体时间复杂度为 O(n),其中 n 是两个字符串中较长的那个的长度。

空间复杂度

  1. 补齐长度

    • 创建新的字符串 binary1 和 binary2,空间复杂度是 O(n)
  2. 逐位相加

    • 使用 StringBuilder 存储结果,空间复杂度是 O(n)
  3. 处理最后的进位

    • 这个操作的空间复杂度是 O(1)
  4. 生成结果

    • result.reverse() 和 toString() 的空间复杂度是 O(n)
  5. 转换为十进制

    • new BigInteger(binaryResult, 2) 的空间复杂度是 O(n)
    • toString(10) 的空间复杂度是 O(n)

综合以上分析,主要的空间复杂度来自于字符串和 StringBuilder 的使用,总体空间复杂度为 O(n),其中 n 是两个字符串中较长的那个的长度。

总结

  • 时间复杂度O(n)
  • 空间复杂度O(n)