问题描述
小U和小R喜欢探索二进制数字的奥秘。他们想找到一个方法,将两个二进制字符串相加并以十进制的形式呈现。这个过程需要注意的是,他们的二进制串可能非常长,所以常规的方法可能无法处理大数。小U和小R希望你帮助他们设计一个算法,该算法能在保证时间复杂度不超过 (O(n^2)) 的前提下,返回两个二进制字符串的十进制求和结果。
做题思路
1. 问题分析
- 二进制字符串相加:我们需要将两个二进制字符串相加,得到一个新的二进制字符串。
- 转换为十进制:将得到的二进制字符串转换为十进制数。
为了实现这个目标,我们可以分两步进行:
- 二进制字符串相加:从最低位开始逐位相加,处理进位。
- 二进制转十进制:将得到的二进制字符串转换为十进制数。
2. 关键点
- 逐位相加:从最低位开始逐位相加,处理进位。
- 字符串操作:使用
StringBuilder来方便地处理字符串的反转和拼接。 - 二进制转十进制:使用
Integer.parseInt方法将二进制字符串转换为十进制数。
3. 解决方案
- 反转二进制字符串:为了从最低位开始处理,我们将两个二进制字符串反转。
- 逐位相加:从最低位开始逐位相加,处理进位,直到所有位都处理完并且没有进位为止。
- 结果反转:将得到的二进制结果字符串反转回正常顺序。
- 转换为十进制:使用
Integer.parseInt方法将二进制字符串转换为十进制数。
做题方式
-
反转二进制字符串:
- 使用
StringBuilder的reverse方法将两个二进制字符串反转。
- 使用
-
逐位相加:
- 初始化一个
StringBuilder来存储结果。 - 初始化一个进位变量
carry,初始值为0。 - 遍历两个字符串的每一位,从最低位开始:
- 获取当前位的数字,如果超出字符串长度则视为0。
- 计算当前位的和以及新的进位。
- 将当前位的结果追加到
StringBuilder中。
- 初始化一个
-
结果反转:
- 将
StringBuilder中的结果字符串反转回正常顺序。
- 将
-
转换为十进制:
- 使用
Integer.parseInt方法将二进制字符串转换为十进制数。
- 使用
详细代码讲解
public class Main {
public static String solution(String binary1, String binary2) {
// 反转二进制字符串以便从最低位开始处理
StringBuilder sb1 = new StringBuilder(binary1).reverse();
StringBuilder sb2 = new StringBuilder(binary2).reverse();
int maxLength = Math.max(sb1.length(), sb2.length());
StringBuilder result = new StringBuilder();
int carry = 0;
for (int i = 0; i < maxLength || carry != 0; i++) {
// 获取当前位的数字
int bit1 = i < sb1.length() ? sb1.charAt(i) - '0' : 0;
int bit2 = i < sb2.length() ? sb2.charAt(i) - '0' : 0;
// 计算当前位的和以及新的进位
int sum = bit1 + bit2 + carry;
result.append(sum % 2);
carry = sum / 2;
}
// 将二进制结果转换为十进制
return Integer.toString(Integer.parseInt(result.reverse().toString(), 2));
}
public static void main(String[] args) {
// 测试用例
System.out.println(solution("101", "110").equals("11")); // true
System.out.println(solution("111111", "10100").equals("83")); // true
System.out.println(solution("111010101001001011", "100010101001").equals("242420")); // true
System.out.println(solution("111010101001011", "10010101001").equals("31220")); // true
System.out.println(solution("11", "1").equals("4")); // true
}
}
代码解析
-
方法定义:
public static String solution(String binary1, String binary2):定义一个静态方法solution,接收两个二进制字符串binary1和binary2,返回一个表示其十进制和的字符串。
-
反转二进制字符串:
StringBuilder sb1 = new StringBuilder(binary1).reverse();:将binary1反转。StringBuilder sb2 = new StringBuilder(binary2).reverse();:将binary2反转。
-
初始化变量:
int maxLength = Math.max(sb1.length(), sb2.length());:获取两个字符串的最大长度。StringBuilder result = new StringBuilder();:初始化一个StringBuilder来存储结果。int carry = 0;:初始化进位变量carry,初始值为0。
-
逐位相加:
for (int i = 0; i < maxLength || carry != 0; i++) {:遍历两个字符串的每一位,直到所有位都处理完并且没有进位为止。int bit1 = i < sb1.length() ? sb1.charAt(i) - '0' : 0;:获取sb1的当前位数字,如果超出长度则视为0。int bit2 = i < sb2.length() ? sb2.charAt(i) - '0' : 0;:获取sb2的当前位数字,如果超出长度则视为0。int sum = bit1 + bit2 + carry;:计算当前位的和。result.append(sum % 2);:将当前位的结果追加到result中。carry = sum / 2;:更新进位。
-
结果反转:
result.reverse();:将result中的结果字符串反转回正常顺序。
-
转换为十进制:
Integer.parseInt(result.toString(), 2);:将二进制字符串转换为十进制数。Integer.toString(...);:将十进制数转换为字符串。
-
测试用例:
System.out.println(solution("101", "110").equals("11"));:测试用例1,输出true表示结果正确。System.out.println(solution("111111", "10100").equals("83"));:测试用例2,输出true表示结果正确。System.out.println(solution("111010101001001011", "100010101001").equals("242420"));:测试用例3,输出true表示结果正确。System.out.println(solution("111010101001011", "10010101001").equals("31220"));:测试用例4,输出true表示结果正确。System.out.println(solution("11", "1").equals("4"));:测试用例5,输出true表示结果正确。
总结
通过使用字符串操作和逐位相加的方法,我们可以在 (O(n)) 时间复杂度内完成两个二进制字符串的相加,并将结果转换为十进制数。这种方法不仅高效,而且简洁,非常适合处理大数的二进制相加问题。
扩展思考
-
大数处理:
- 如果二进制字符串非常长,超过了
Integer的范围,可以使用BigInteger类来处理大数。 BigInteger类提供了大数的加法和二进制转换方法,可以轻松处理非常长的二进制字符串。
- 如果二进制字符串非常长,超过了
-
优化:
- 如果需要进一步优化性能,可以考虑使用更高效的字符串操作方法,或者使用位运算来处理二进制相加。
-
实际应用:
- 这种方法在数据处理和算法竞赛中非常常见,尤其是在需要高效处理二进制数据的情况下。
- 例如,在密码学和数据压缩算法中,经常需要处理大数的二进制操作。