面试题2:二进制加法
力扣链接:https://leetcode-cn.com/problems/JFETK5/
题目描述
给定两个01字符串a和b,请计算它们的和,并以二进制字符的形式输出。输入为非空字符串且只包含数字1和0.
- 每个字符串仅有字符’0’和’1’组成。
- 1 <= a.length,b.length <=104
- 如果字符串不是"0",就都不含前导零。
输入样例1
a=“11”,b=“10”
输出样例1
“101”
输入样例2
a=“1010”,b=“1011”
输出样例2
“10101”
解析
看到题目之后,最先想到的解法可能是:先将二进制字符串转换成int型整数或long型整数,然后把两个整数相加得到和之后再将和转换成二进制字符串。例如,将二进制字符串“11”转换成3,“10"转换成2,两个整数的和为5,将之转换成二进制字符串得到"101”。但是当两个二进制字符串很长很长的时候就会导致数据的溢出,因此此解法行不通,需要另想办法。
既然这道题是二进制的加法,那么我们就放在二进制中去做。
题解
模仿十进制的加法,从字符串的最右端开始出发向左做加法,相加同一个位置的两个数位,如果前一位有进位还要加上进位,与十进制逢10进1把不同的是二进制是逢2进1。以下是编程过程中需要注意的地方:
- 因为题目中说“只要字符串不是“0”,就不含前导零”,考虑到两个二进制的字符串长度可能不一样,所以在进行对应位加法的时候,如果当前下标超出了某个字符串的范围,就用0来代替。
- 因为要考虑到进位,所以需要在循环的外面设置一个变量记录进位值。
- 如果循环结束之后,进位值等于1,还需要把’1‘加入到结果字符串中。
- 因为是从最低位开始计算的,所以最后需要把结果字符串reverse以下再返回。
class Solution {
public:
string addBinary(string a, string b) {
int n1=a.length()-1,n2=b.length()-1;
string res="";
int pd=0;//记录进位
while(n1>=0 || n2>=0){
int num1=n1>=0?a[n1]-'0':0;
int num2=n2>=0?b[n2]-'0':0;
int sum=num1+num2+pd;
pd=sum>=2?1:0;
sum=sum>=2?sum-2:sum;
res+=sum+'0';
n1--;
n2--;
}
if(pd==1) res+='1';
reverse(res.begin(),res.end());
return res;
}
};
/*
将两个字符串右对齐,相加每个位置的数字
*/
知识补充
二进制的位运算
二进制的位运算只有两种:非、与、或、异或、左移、右移。
- 非运算就是对整数的二进制按位取反,0取反得1,1取反得0。
例如:~00001010 = 11110101 ,~10001010 = 01110101
- 左移运算符m << n表示把m左移n位。如果左移n位,最左边的n位被丢弃,同时在最右边补上n个0.
00001010 <<2 = 00101000,10001010<<3 = 01010000
- 右移运算符m >> n表示把m右移n位。如果m是无符号整数,那么在右移n位之后在最左边补上n个0;如果m是有符号整数,那么在右移n位之后在最左边补上n个最高位。
00001010 >>2 = 00000010,10001010 >>3 = 11110001