题目解析:二进制字符串相加并转换为十进制
1. 题目背景与问题理解
小U和小R喜欢探索二进制数字的奥秘。他们想找到一个方法,将两个二进制字符串相加并以十进制的形式呈现。这个过程需要注意的是,他们的二进制串可能非常长,所以常规的方法可能无法处理大数。小U和小R希望你帮助他们设计一个算法,该算法能在保证时间复杂度不超过O(n^2)的前提下,返回两个二进制字符串的十进制求和结果。
2. 问题分析
2.1 输入与输出
- 输入:两个二进制字符串
binary1和binary2。 - 输出:一个十进制字符串,表示两个二进制字符串相加的结果。
2.2 关键点
- 大数问题:由于二进制字符串可能非常长,直接将它们转换为整数进行计算可能会导致溢出。因此,我们需要使用字符串来处理这些大数。
- 时间复杂度:算法的时间复杂度应不超过
O(n^2),其中n是二进制字符串的长度。
3. 解题思路
3.1 对齐二进制字符串
由于两个二进制字符串的长度可能不同,我们需要在较短的字符串前面补0,使得两个字符串长度相同。这样可以方便我们逐位相加。
3.2 逐位相加
从最低位(字符串的最后一位)开始,逐位相加,并记录进位。每一位的相加结果可以通过以下公式计算:
。
其中,bit1 和 bit2 分别是当前位的二进制数字,carry 是前一位的进位。
3.3 处理进位
在每一位相加时,需要考虑前一位的进位。如果当前位的和大于1,则会产生进位。
3.4 生成结果字符串
将每一位的结果和进位组合成最终的二进制字符串。由于我们从最低位开始相加,最终的结果字符串需要反转。
3.5 转换为十进制
将最终的二进制字符串转换为十进制字符串。可以使用 BigInteger 类来处理大数问题。
4. 示例解法
4.1 对齐二进制字符串
假设 binary1 = "101",binary2 = "110":
- 对齐后:
binary1 = "101",binary2 = "011"
4.2 逐位相加
从最低位开始逐位相加:
- 第1位:
1 + 1 + 0 = 2,结果为0,进位为1 - 第2位:
0 + 1 + 1 = 2,结果为0,进位为1 - 第3位:
1 + 0 + 1 = 2,结果为0,进位为1
最终结果为 000,进位为 1,所以最终结果为 1000。
4.3 转换为十进制
将 1000 转换为十进制:
1000对应的十进制为8
5. 代码详解
import java.math.BigInteger;
public class Main {
public static String solution(String binary1, String binary2) {
// 对齐二进制字符串
int maxLength = Math.max(binary1.length(), binary2.length());
binary1 = String.format("%" + maxLength + "s", binary1).replace(' ', '0');
binary2 = String.format("%" + maxLength + "s", binary2).replace(' ', '0');
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;
// 计算当前位的结果和进位
result.append(sum % 2);
carry = sum / 2;
}
// 处理最后的进位
if (carry != 0) {
result.append(carry);
}
// 反转结果字符串
result.reverse();
// 将二进制字符串转换为十进制字符串
return new BigInteger(result.toString(), 2).toString(10);
}
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"));
}
}
5.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');
- 使用
Math.max找到两个字符串的最大长度。 - 使用
String.format在较短的字符串前面补0,使得两个字符串长度相同。
5.2 逐位相加
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;
// 计算当前位的结果和进位
result.append(sum % 2);
carry = sum / 2;
}
- 从最低位开始逐位相加,并记录进位。
- 使用
charAt获取当前位的二进制数字,并将其转换为整数。 - 计算当前位的和,并更新进位。
5.3 处理进位
if (carry != 0) {
result.append(carry);
}
- 如果最后一位相加后仍有进位,将其添加到结果字符串中。
5.4 生成结果字符串
result.reverse();
- 由于我们从最低位开始相加,最终的结果字符串需要反转。
5.5 转换为十进制
return new BigInteger(result.toString(), 2).toString(10);
- 使用
BigInteger类将二进制字符串转换为十进制字符串。
6 总结
该算法通过逐位相加两个二进制字符串并处理进位,最终将结果转换为十进制字符串。时间复杂度为 O(n),其中 n 是二进制字符串的最大长度,主要消耗在逐位相加和字符串反转操作上。空间复杂度为 O(n),用于存储对齐后的二进制字符串和结果字符串。使用 BigInteger 类处理大数转换,确保了算法的稳定性和正确性。整体上,该算法高效且适用于处理大数问题。