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

64 阅读6分钟

二进制之和

问题描述

小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'

同一道题,不同语言之间有着完全不一样的做法。

Python题解

计算两个二进制字符串的十进制求和结果最直接的做法便是:

  1. 转换为整数:首先将两个二进制字符串转换为十进制整数。
  2. 求和:然后将这两个十进制整数相加。
  3. 返回结果:最后返回它们的和。

由于直接将二进制字符串转换为十进制数可能会遇到大数问题,因此我们需要采用一种能够处理大数的方法。但Python 的内置类型支持大数运算,因此可以直接使用 Python 的 int() 函数将二进制字符串转换为十进制整数,指定基数为 2,这使得该题在使用Python语言情况下很容易实现。

def solution(binary1, binary2):
    num1 = int(binary1, 2)
    num2 = int(binary2, 2)
    total = num1 + num2
    return str(total)

正是因为Python 对大数的支持非常好,可以直接使用内置的 int() 函数将二进制字符串转换为十进制整数,然后再进行求和。Python 的 int() 函数可以处理任意长度的二进制字符串,而不会溢出。

Java题解

若Java需要采用Python的这套解决思路导航,由于Java 中没有像 Python 那样的内置大数支持,因此需要使用 BigInteger 类来处理大数。BigInteger 类提供了对任意精度整数的支持,可以用来处理任意长度的二进制字符串。

    public static String solution(String binary1, String binary2)  {

        BigInteger num1 = new BigInteger(binary1, 2);
        BigInteger num2 = new BigInteger(binary2, 2);

        BigInteger total = num1.add(num2);
        
        return total.toString();
    }

此外,还有逐位相加,处理进位,最终将结果转换为十进制的做法,下面是该做法的实现代码:

public static String solution(String binary1, String binary2) {
        // Please write your code here
        long ans = 0;long index = 1;char last = '0';
        for(int i=binary1.length()-1,j=binary2.length()-1;i>=0 || j>=0 || last!='0';){
            char b1 = '0';
            if(i>=0) b1 = binary1.charAt(i--);
            char b2 = '0';
            if(j>=0) b2 = binary2.charAt(j--);
            if(last=='0'){
                if(b1=='1' && b2=='1'){
                    last = '1';
                }else if(b1=='1' || b2=='1'){
                    ans += index;
                }
            }else {
                if(b1=='0' && b2=='0'){
                    ans += index;
                    last = '0';
                }else if(b1=='1' && b2=='1'){
                    ans += index;
                }
            }
            index*=2;
        }
        return Long.toString(ans);
    }   

为什么不同语言对于此题有着完全不一样的做法呢?

1.大数支持:

Python:Python 的 int 类型可以自动处理大数,不需要额外的类或库。
Java:Java 的 int 和 long 类型有固定的范围,超过范围会溢出。因此,需要使用 BigInteger 类来处理大数。

2.内置函数:

Python:Python 提供了 int() 函数,可以直接将二进制字符串转换为十进制整数。
Java:Java 需要使用 BigInteger 类的构造函数来将二进制字符串转换为 BigInteger 对象。

3.字符串操作:

Python:Python 的字符串操作非常灵活,可以直接使用字符串进行各种操作。
Java:Java 的字符串操作相对复杂,需要使用 String 类的方法来处理字符串。

Python的大数支持的实现思路

Python 对大数的支持非常强大,这得益于其内置的整数类型 int 的设计。Python 的 int 类型在内部使用了一种动态长度的整数表示方法,可以自动处理任意大小的整数,而不会像 C 或 Java 那样受到固定大小的限制。下面是 Python 大数实现的底层机制的详细解释:

1. 动态长度的整数表示

Python 的 int 类型在内部使用了一种称为“长整数”的表示方法。这种表示方法允许整数的长度根据需要动态扩展,从而可以表示任意大的整数。

2. 内存管理

内存分配:Python 的 int 类型在内部使用一个数组来存储整数的各个部分。每个部分通常是一个固定大小的整数(通常是 30 位或 15 位,具体取决于平台)。当整数的大小超过当前数组的容量时,Python 会自动扩展数组的大小。
内存释放:当一个大整数不再被引用时,Python 的垃圾回收机制会自动释放其占用的内存。

3. 内部表示

字节序:Python 的大整数在内部是以小端字节序存储的,这意味着最低有效位存储在数组的起始位置。
位宽:每个部分的位宽通常是 30 位或 15 位,具体取决于平台。32 位系统上通常使用 15 位,64 位系统上通常使用 30 位。这样设计的原因是为了避免在进行乘法和加法运算时发生溢出。

4. 运算实现

加法和减法:Python 的大整数加法和减法运算通过逐位进行,类似于手工计算的方式。如果有进位或借位,会相应地调整相邻的位。
乘法:Python 的大整数乘法使用了 Karatsuba 算法或其他高效的乘法算法,这些算法的时间复杂度比传统的 O(n^2) 更低。
除法和取模:Python 的大整数除法和取模运算也使用了高效的算法,如 Newton-Raphson 迭代法。

5. 优化

缓存:Python 会对常用的小整数(通常是 -5 到 256 之间的整数)进行缓存,以提高性能。
内联:对于简单的整数运算,Python 解释器会尝试将这些运算内联,以减少函数调用的开销。