考察内容:对字符串的处理以及对于二进制工作原理的理解,建议简单了解二进制原理之后食用
问题描述
小U和小R喜欢探索二进制数字的奥秘。他们想找到一个方法,将两个二进制字符串相加并以十进制的形式呈现。这个过程需要注意的是,他们的二进制串可能非常长,所以常规的方法可能无法处理大数。小U和小R希望你帮助他们设计一个算法,该算法能在保证时间复杂度不超过O(n^2)的前提下,返回两个二进制字符串的十进制求和结果。
算法分析
在这个问题中,我们需要设计一个算法来处理两个可能非常长的二进制字符串的加法。我们的目标是将这两个二进制字符串相加,并以十进制的形式返回结果。为了实现这一点,我们可以模拟二进制加法的过程,同时考虑到进位的情况。这需要对于二进制编码有一定的了解。
解题思路
1、变量的定义以及初始化:
int carry = 0;
int result = 0;
StringBuilder target = new StringBuilder();
StringBuilder sb1 = new StringBuilder(binary1);
StringBuilder sb2 = new StringBuilder(binary2);
- carry:用于存储二进制加法中的进位值,初始化为0。
- result:用于存储最终结果,先初始化为0。
- target:用于构建二进制相加之后的字符串。(注意要使用StringBuilder类型而不是String)。
- sb1与sb2:用于存储输入的两个二进制字符串(同理要用StringBuilder方便后续补0)。
- 二进制字符串长度调整
int length = binary1.length()>binary2.length()?binary1.length():binary2.length();
if(binary1.length()>binary2.length()){
StringBuilder replacement = new StringBuilder();
for (int i = 0; i < binary1.length() - binary2.length(); i++) {
replacement.append('0');
}
sb2.insert(0, replacement.toString());
}
if(binary1.length()<binary2.length()){
StringBuilder replacement = new StringBuilder();
for (int i = 0; i < binary2.length() - binary1.length(); i++) {
replacement.append('0');
}
sb1.insert(0, replacement.toString());
}
sb1.reverse();
sb2.reverse();
- 首先确定两个二进制字符串中的较长长度length。
- 如果binary1较长,通过循环在sb2前面添加足够数量的0,使其长度与binary1相同;反之,如果binary1较短,则在sb1前面添加0。这一步确保了后续二进制加法的顺利进行,因为只有长度相同才能逐位相加。
- 最终将sb1和sb2反转,目的是为了从二进制数的最低位(最右边位)开始相加,这符合二进制加法的计算规则。
3、 二进制加法操作
for(int i=0;i<length;i++){
int res1 = (sb1.charAt(i)=='0')?0:1;
int res2 = (sb2.charAt(i)=='0')?0:1;
int value = res1+res2+carry;
if(value>=2) {
value%=2;
carry=1;
}else{
carry=0;
}
char ch = (value == 0) ? '0' : '1';
target.append(ch);
}
if(carry==1)target.append('1');
System.out.println(target.toString());
for(int i=0;i<target.length();i++){
int res = (target.charAt(i)=='0')?0:1;
result += res*(int) Math.pow(2.0,i);
}
逐位进行二进制加法。
- 首先将sb1和sb2当前位的字符转换为十进制的0或1(存储在res1和res2中),然后加上进位carry得到value。
- 如果value大于等于2,说明有进位,将value对2取余得到本位结果,并将进位carry设为1;否则进位设为0。
- 将本位结果(0或1)转换为字符添加到target中。
- 循环结束后,如果最后还有进位(carry为1),则在target末尾添加一个1
4、二进制结果转化为十进制
for(int i=0;i<target.length();i++){
int res = (target.charAt(i)=='0')?0:1;
result += res*(int) Math.pow(2.0,i);
}
System.out.println(result);
- 再次遍历target字符串。
- 将当前位的字符转换为十进制的0或1(存储在res中),然后乘以2^i(其中i是当前位的索引)并累加到result中,实现二进制到十进制的转换。
完整代码如下(仅供参考):
public class Main {
public static String solution(String binary1, String binary2) {
// Please write your code here
int carry = 0;
int result = 0;
StringBuilder target = new StringBuilder();
StringBuilder sb1 = new StringBuilder(binary1);
StringBuilder sb2 = new StringBuilder(binary2);
int length = binary1.length()>binary2.length()?binary1.length():binary2.length();
if(binary1.length()>binary2.length()){
StringBuilder replacement = new StringBuilder();
for (int i = 0; i < binary1.length() - binary2.length(); i++) {
replacement.append('0');
}
sb2.insert(0, replacement.toString());
}
if(binary1.length()<binary2.length()){
StringBuilder replacement = new StringBuilder();
for (int i = 0; i < binary2.length() - binary1.length(); i++) {
replacement.append('0');
}
sb1.insert(0, replacement.toString());
}
sb1.reverse();
sb2.reverse();
for(int i=0;i<length;i++){
int res1 = (sb1.charAt(i)=='0')?0:1;
int res2 = (sb2.charAt(i)=='0')?0:1;
int value = res1+res2+carry;
if(value>=2) {
value%=2;
carry=1;
}else{
carry=0;
}
char ch = (value == 0) ? '0' : '1';
target.append(ch);
}
if(carry==1)target.append('1');
System.out.println(target.toString());
for(int i=0;i<target.length();i++){
int res = (target.charAt(i)=='0')?0:1;
result += res*(int) Math.pow(2.0,i);
}
System.out.println(result);
return String.valueOf(result);
}
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"));
}
}
总结
通过模拟二进制加法的过程,我们可以有效地计算出两个二进制字符串的十进制和。这种方法避免了直接处理大数的问题,同时也保证了时间复杂度不超过O(n^2)。