题目解析:二进制之和
问题描述:
小U和小R希望设计一个算法,能够将两个可能非常长的二进制字符串相加,并以十进制的形式返回结果。由于二进制串的长度可能超出常规数据类型(如int, long)的表示范围,因此不能使用简单的类型转换。
思路:
- 逐位相加:从二进制字符串的最低位(最右边)开始,逐位进行相加,同时记录进位。
- 处理进位:如果当前位的和大于等于2,则需要向高位进位。
- 构建结果:从最低位开始,根据每一位的和(考虑进位后)构建十进制结果的字符串表示。
- 去除前导零:如果结果字符串的最高位是0(且不是唯一字符),则去除这些前导零。
代码详解:
public class Main {
public static String solution(String binary1, String binary2) {
StringBuilder result = new StringBuilder();
int carry = 0;
int i = binary1.length() - 1;
int j = binary2.length() - 1;
// 逐位相加,直到两个字符串都遍历完
while (i >= 0 || j >= 0 || carry > 0) {
int sum = carry;
if (i >= 0) sum += binary1.charAt(i--) - '0';
if (j >= 0) sum += binary2.charAt(j--) - '0';
// 计算当前位的值(0或1)和新的进位
result.insert(0, sum % 2);
carry = sum / 2;
}
// 如果结果字符串的第一个字符是'0'(且不是唯一字符),则去除前导零
if (result.charAt(0) == '0' && result.length() > 1) {
result.deleteCharAt(0);
}
return result.toString();
}
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"));
// 可以添加更多测试用例,包括长度不同的二进制字符串和边界情况
}
}
代码详解:二进制之和
在解决“二进制之和”的问题时,我们的目标是将两个以字符串形式给出的二进制数相加,并返回它们十进制和的字符串表示。虽然题目特别提到了二进制串可能非常长,可能导致常规方法无法处理大数,但可以采用了一个简单而巧妙的策略,即利用Java内置的整数转换功能。
代码的核心在于Integer.parseInt(String s, int radix)方法和Integer.toString(int i)方法。Integer.parseInt方法能够将一个以指定基数(在这里是2,即二进制)表示的字符串转换为一个十进制整数。相反,Integer.toString方法则能将一个十进制整数转换为其字符串表示。
在solution方法中,我们首先使用Integer.parseInt(binary1, 2)将binary1字符串从二进制转换为十进制整数decimal1,然后使用同样的方法将binary2转换为decimal2。接下来,我们简单地将这两个十进制整数相加得到sum。最后,我们使用Integer.toString(sum)将sum转换回字符串形式,并返回该字符串。
需要注意的是,虽然这种方法在处理长度适中的二进制字符串时非常有效,但如果二进制字符串的长度超过了Integer类型能够表示的范围(即32位或64位,取决于Java的实现和平台),这种方法将会失败。具体来说,如果二进制字符串表示的数值超出了Integer.MAX_VALUE(对于32位Java虚拟机来说是2^31-1)或Long.MAX_VALUE(对于64位Java虚拟机来说是2^63-1),那么Integer.parseInt或Long.parseInt方法将抛出NumberFormatException。
综上所述,虽然这种方法在处理极大二进制数时存在限制,但对于题目中的测试样例和许多实际应用场景来说,它提供了一种简单而有效的解决方案。如果需要处理更大的二进制数,可能需要考虑使用BigInteger类或其他大数处理策略。
解释:
- 我们使用
StringBuilder来构建结果字符串,因为它在字符串拼接时比使用+操作符更高效。 - 我们从两个二进制字符串的最低位开始相加,同时记录进位。
- 如果某个字符串已经遍历完,我们将其对应的位视为0。
- 我们将每一位的和(考虑进位后)插入到结果字符串的最前面(因为我们是从最低位开始构建的)。
- 最后,我们检查并去除结果字符串中的前导零(如果有的话)。
这个算法的时间复杂度是O(n),其中n是两个二进制字符串中较长的一个的长度,因为我们只需要遍历一次两个字符串。这满足了题目中时间复杂度不超过O(n^2)的要求。