二进制之和
问题描述
小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题解
计算两个二进制字符串的十进制求和结果最直接的做法便是:
- 转换为整数:首先将两个二进制字符串转换为十进制整数。
- 求和:然后将这两个十进制整数相加。
- 返回结果:最后返回它们的和。
由于直接将二进制字符串转换为十进制数可能会遇到大数问题,因此我们需要采用一种能够处理大数的方法。但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 解释器会尝试将这些运算内联,以减少函数调用的开销。