8 二进制之和
给定两个二进制字符串,返回他们的和(用十进制字符串表示)。输入为非空字符串且只包含数字 1 和 0 ,请考虑大数问题。时间复杂度不要超过 O(n^2),其中 n 是二进制的最大长度。
输入格式
每个样例只有一行,两个二进制字符串以英文逗号“,”分割
输出格式
输出十进制格式的两个二进制的和
输入样例:
101,110
输出样例:
11
数据范围:
每个二进制不超过 100 个字符,JavaScript 语言下请考虑大数的情况。
解题思路
1. 二进制转十进制
由于二进制字符串长度可能达到 100 位,直接转换为整数类型(如 int 或 long)可能会导致溢出。因此,需要使用字符串来模拟二进制到十进制的转换过程。
转换方法:
-
初始化:将十进制结果初始化为字符串
"0"。 -
逐位处理:从二进制字符串的最高位(左侧)开始,依次处理每一位:
- 乘以2:将当前的十进制字符串乘以
2。这是因为二进制的每一位代表2的幂次。 - 加1(如果当前位为1) :如果当前处理的二进制位是
'1',则在乘以2的结果上加1。
- 乘以2:将当前的十进制字符串乘以
通过这种方式,逐位累加,最终得到完整的十进制字符串表示。
示例:
-
二进制字符串
101:-
初始十进制字符串:
"0" -
处理第1位
'1':- 乘以2:
0 * 2 = 0 - 加1:
0 + 1 = 1 - 十进制字符串更新为
"1"
- 乘以2:
-
处理第2位
'0':- 乘以2:
1 * 2 = 2 - 加0:
2 + 0 = 2 - 十进制字符串更新为
"2"
- 乘以2:
-
处理第3位
'1':- 乘以2:
2 * 2 = 4 - 加1:
4 + 1 = 5 - 十进制字符串更新为
"5"
- 乘以2:
-
最终十进制结果:
"5"
-
2. 十进制字符串相加
转换得到两个十进制字符串后,需要将它们相加得到最终的十进制和。由于这两个字符串可能非常长(大于常规数据类型的范围),同样需要使用字符串模拟手动加法。
加法方法:
-
从右到左遍历:同时从两个十进制字符串的末尾(最低位)开始,逐位相加。
-
处理进位:
- 每一位相加的结果如果大于或等于
10,则需要进位到更高位。
- 每一位相加的结果如果大于或等于
-
构建结果字符串:将每一位的和(考虑进位)添加到结果字符串的前端。
-
最终结果:遍历完成后,结果字符串即为两数之和的十进制表示。
示例:
-
十进制字符串
"5"和"6":-
从右到左:
5 + 6 = 11- 记录个位数
1,进位1
-
由于已经遍历完所有位,且有进位
1,将其添加到结果前端。 -
最终结果:
"11"
-
3. 整体流程总结
- 输入解析:分割输入,获取两个二进制字符串。
- 二进制转十进制:将每个二进制字符串转换为对应的十进制字符串。
- 十进制相加:将两个十进制字符串相加,得到最终的十进制和。
- 输出结果:返回最终的十进制字符串作为结果。
算法实现
public class Main {
public static String solution(String binary1, String binary2) {
// Please write your code here
// 将两个二进制字符串转换为十进制字符串
String dec1 = binaryToDecimal(binary1);
String dec2 = binaryToDecimal(binary2);
// 将两个十进制字符串相加
String decimalSum = addStrings(dec1, dec2);
return decimalSum;
}
private static String binaryToDecimal(String bin) {
String decimal = "0";
for(int i = 0; i < bin.length(); i++) {
char c = bin.charAt(i);
// 将当前十进制数乘以2
decimal = multiplyByTwo(decimal);
// 如果当前二进制位为'1',则加1
if(c == '1') {
decimal = addOne(decimal);
}
}
return decimal;
}
private static String addOne(String num) {
StringBuilder sb = new StringBuilder();
int carry = 1; // 初始进位为1,因为是加1
// 从右到左遍历字符串
for(int i = num.length() - 1; i >= 0; i--) {
int digit = num.charAt(i) - '0';
int temp = digit + carry;
carry = temp / 10;
sb.append(temp % 10);
}
if(carry != 0) {
sb.append(carry);
}
// 反转字符串
return sb.reverse().toString();
}
private static String multiplyByTwo(String num) {
StringBuilder sb = new StringBuilder();
int carry = 0;
// 从右到左遍历字符串
for(int i = num.length() - 1; i >= 0; i--) {
int digit = num.charAt(i) - '0';
int temp = digit * 2 + carry;
carry = temp / 10;
sb.append(temp % 10);
}
if(carry != 0) {
sb.append(carry);
}
// 反转字符串
return sb.reverse().toString();
}
private static String addStrings(String num1, String num2) {
StringBuilder sb = new StringBuilder();
int carry = 0;
int i = num1.length() - 1;
int j = num2.length() - 1;
// 从右到左遍历两个字符串
while(i >= 0 || j >= 0 || carry != 0) {
int digit1 = (i >= 0) ? (num1.charAt(i) - '0') : 0;
int digit2 = (j >= 0) ? (num2.charAt(j) - '0') : 0;
int sum = digit1 + digit2 + carry;
carry = sum / 10;
sb.append(sum % 10);
i--;
j--;
}
// 反转字符串
return sb.reverse().toString();
}
public static void main(String[] args) {
// You can add more test cases here
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"));
}
}