问题描述
小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'
由于可能的二进制串长度非常长,所以常规的整数类型可能无法处理,因此需要将二进制数当做字符串来进行处理,一个思路就是先比较两个二进制字符的长度,将长度较短的那个字符串的前面补0,使得两个字符串的长度一致,然后再从后向前遍历两个字符串,对于两个字符串的每个字符进行加法,如果加起来等于0或者1则不用进位,如果大于等于2需要进行,在初始时设置进位为0,并且使用一个新的字符串来保存我们逐步相加的结果,当完成二进制加法之后,我们将保存的结果转换成十进制数。然后返回结果,代码如下:
std::string solution(std::string binary1, std::string binary2) {
std::string tempstr;
int n1 = binary1.length();
int n2 = binary2.length();
if(n1 > n2)
for(int i = 0 ; i < n1 - n2 ; i++)
binary2 = '0'+binary2;
else
for(int i = 0 ; i < n2 - n1 ; i++)
binary1 = '0'+binary1;
int n = std::max(n1,n2);
int cnt = 0;
for(int i = n-1 ; i >= 0 ;i--)
{
int num1 = binary1[i] - '0';
int num2 = binary2[i] - '0';
int total = num1 + num2 + cnt;
if(total >= 2)
{
cnt = 1;
total -= 2;
}
else
cnt = 0;
tempstr = std::to_string(total) + tempstr;
}
if(cnt == 1)
tempstr = '1' + tempstr;
int ans = 0;
for(int i = 0 ; i < tempstr.length();i++)
{
ans += (tempstr[i]-'0') * pow(2,tempstr.length()-i-1);
}
return std::to_string(ans);
}
这是AI刷题题库里面的一道困难题,但是实际思路并不难想,主要是要熟悉对字符串的操作,以上代码实现的复杂度为o(n^2),并不是最优解,在长度补齐部分,时间复杂度为o(n),在二进制相加部分,时间复杂度也是o(n),在拼接tempstr的时候,虽然拼接操作本身的复杂度是 O(1)O(1)O(1),但在每次拼接时,tempstr 的长度可能会增加,导致整体的拼接复杂度变成 O(n^2),因此对于算法的改进可以考虑将tempstr的拼接进行优化,我们可以将这一部分改成简单字符的拼接
cnt = total / 2;
tempstr += (total % 2) + '0';
可以将时间复杂度有效的降到o(n),在最后的十进制转换部分,时间复杂度也是o(n),因此可以将算法的整体复杂度优化到o(n)。 以下是参加青训营刷题过程中的一些小感悟:在刷题过程中最重要的是快速构建初步的思路,然后就是在大量刷题的基础上掌握了对代码的熟练度,能够将思路构建成代码,其次就是对于代码的优化,某些函数或者某些用法的效率可能更高,这些都是在大量刷题的基础上才能掌握的,然后就是在c++中,有太多的便捷函数和方法可以直接使用,需要在大量的运用基础上才能熟练掌握和应用。