问题描述
小U和小R喜欢探索二进制数字的奥秘。他们想找到一个方法,将两个二进制字符串相加并以十进制的形式呈现。这个过程需要注意的是,他们的二进制串可能非常长,所以常规的方法可能无法处理大数。小U和小R希望你帮助他们设计一个算法,该算法能在保证时间复杂度不超过O(n^2)的前提下,返回两个二进制字符串的十进制求和结果。
测试样例
样例1:
输入:binary1 = "101" ,binary2 = "110" 输出:'11'
样例2:
输入:binary1 = "111111" ,binary2 = "10100" 输出:'83'
样例3:
输入:binary1 = "111010101001001011" ,binary2 = "100010101001" 输出:'242420'
样例4:
输入:binary1 = "111010101001011" ,binary2 = "10010101001" 输出:'31220'
样例5:
输入:binary1 = "11" ,binary2 = "1" 输出:'4'
解题思路
-
由于二进制数过长,直接转换肯定是不行的,我们通过模拟加法(高精度)得到求和后的字符串
- 举个例子,模拟二进制加法 , 我们从低位开始模拟
- ,进制为,进位,
- ,进制为,进位,
- ,进位为,进位, 剩
- ,进位为,进位, 剩
- 由于存储的是低位到高位,我们进行反转后就是答案
- 如果想计算其他进制的求和,把换成相应进制即可
-
二进制加法解决了,现在考虑如何把求和后的二进制数转为十进制
-
常规的二进制转十进制计算方法为:
- 可以看出足够大时,我们无法计算出(请忽略)
- 考虑将式子拆分,比如前两项
- 此时可以和第二项合并得
- 我们把此时括号中的设为,来推导下一项
- 按照一样的方法可以得到
- 可以看出是一个逐渐相乘的过程,我们最后会计算到
- 括号中就是
- 的操作我们可以换为高精度加法,就不会导致溢出问题了
核心代码
//高精度加法
string calc(string a, string b, int d) {
string ans = "";
int i = a.size() - 1;
int j = b.size() - 1;
int carry = 0;
while(i >= 0 || j >= 0 || carry > 0) {
int s = 0;
if(i >= 0) s += a[i] -'0', i--;
if(j >= 0) s += b[j] -'0', j--;
s += carry;
carry = s / d;
s = s % d;
ans += to_string(s);
}
reverse(ans.begin(),ans.end());
return ans;
}
std::string solution(std::string binary1, std::string binary2) {
string s = calc(binary1, binary2, 2);
string ans = "0";
for(int i=0; i < s.length(); i++) {
ans = calc(calc(ans, ans, 10),string(1,s[i]), 10);
}
return ans;
}