@Leetcode二进制加法
这是一道不需要看题干就知道在问啥的题,a+b的二进制版本,来看题干:
给定两个二进制字符串,返回他们的和(用二进制表示)。输入为非空字符串且只包含数字 1 和 0。
示例 1:
输入: a = “11”, b = “1”
输出: “100”
示例 2:
输入: a = “1010”, b = “1011”
输出: “10101”
首先在落笔之前,请每个小白coder不要犯和笔者一样的错误:不要试图将二进制转换成十进制来进行计算!其实这个道理稍微思索就能明白,二进制向十进制转换时,最高位的计算是2的位数-1的次方,然而如果样例是个100位的二进制数,很容易就会因为2的100次方过大而爆栈。那么既然不能转换成十进制,就在二进制的情况下应该如何计算呢?我们要巧妙地应用字符串与ASCII码的加减,请看代码:
class Solution {
public:
string addBinary(string a, string b) {
int x=a.size();
int y=b.size();
while(x>y){
b='0'+b;
y++;
}
while(y>x){
a='0'+a;
x++;
}
for(int i=a.size()-1;i>0;i--){
a[i]=a[i]+b[i]-'0';
if(a[i]>='2'){
a[i]=(a[i]-'0')%2+'0';
a[i-1]=a[i-1]+1;
}
}
a[0]=a[0]+b[0]-'0';
if(a[0]>='2'){
a[0]=(a[0]-'0')%2+'0';
a='1'+a;
}
return a;
}
};
笔者在写出这份代码之前试验了很多不同的写法,但是最终发现,在原有的string a和b上进行更改,才是最快的操作,如果要新开string类型的话,在不知道长度的情况下是不可以使用下标的,如果把string的数据导入int型数组组再进行处理也不是不行,但终归是复杂,在leetcode上大佬们的题解中也有几乎相同的方法,接下来笔者将详细解析本题的思路。
首先需要明确的是,在发现不能进制转换之后,本题的思路就几乎可以确定是使用“模拟法”了。模拟法的意思是模拟某种简单或者精炼的语言对所需解决的问题进行描述,从而达到对问题的简化或者分解的目的。这道题模拟的是小学时我们就能接触到的竖式计算方法,将 两个加数从最低位开始逐一相加并判断是否需要进位,如果需要则在下一对加数中加上进位的数再进行计算。这样得到的计算单元不会溢出,同时数量也是在可控的范围内的。
具体的操作需要注意铺垫和细节。首先两个加数必须位数相同,位数较少的那个要在前面补0来补齐位数。由于是字符串类型,所以直接在前面加‘0’就可以达到目的。补齐位数后进行计算,也就是for循环之中的内容。由于字符串之中存储的并非整型,则a[i]与b[i]相加之后就会多出一个‘0’,需要减去,在判断是否需要进位,也就是>=2时也同样是对‘2’进行操作,同理,在%2算余数是要先减去一个‘0’才能进行整型的计算。
下标0位依然需要单独判断,从而决定是否需要增加数位,判断方法与之前的相同,只不过进位只需要直接在前面加上‘1’就行了。在a字符串上直接修改的好处是省去了很多不必要的步骤,节省了空间,但是需要理清逻辑,并且注意a被修改的对象的修改语句的位置,这可能影响到最终的解答,这和“加一”判断中的&&号两边不能交换位置类似。
最后给大家提个醒,小白笔者也是被朋友提醒的,请注意,string c[1000]并不是开一个有1000个位置的字符串c,而是开了1000个c…