题目
给你两个二进制字符串 a
和 b
,以二进制字符串的形式返回它们的和。
示例 1:
输入:a = "11", b = "1" 输出:"100"
示例 2:
输入:a = "1010", b = "1011" 输出:"10101"
思路
二进制求和需要考虑进位以及把两个数对齐的操作。官方题解中是将两个字符串反转,这样从低下标开始相加其实就是实际的加法过程了。对于进位问题,我原本想的是设一个变量 flag ,然后考虑 a[i] + b[i] + flag 对应的情况,官方题解中以 carry 表示进位,那么每一位的结果实际上是 (carry + a[i] + b[i])%2 ,不需要用 if 进行判断,进位就是 (carry + a[i] + b[i])/2,还挺妙的。如果最后进位不为 0 的话要在末尾加一个 1 ,最后反转结果得到最终答案。 官方题解的代码写的非常简洁,学到了反转字符串和 fmax()函数。
代码
void reserve(char* s) {
int len = strlen(s);
for (int i = 0; i < len / 2; i++) {
char t = s[i];
s[i] = s[len - i - 1], s[len - i - 1] = t;
}
}
char* addBinary(char* a, char* b) {
reserve(a);
reserve(b);
int len_a = strlen(a), len_b = strlen(b);
int n = fmax(len_a, len_b), carry = 0, len = 0;
char* ans = (char*)malloc(sizeof(char) * (n + 2));
for (int i = 0; i < n; ++i) {
carry += i < len_a ? (a[i] == '1') : 0;
carry += i < len_b ? (b[i] == '1') : 0;
ans[len++] = carry % 2 + '0';
carry /= 2;
}
if (carry) {
ans[len++] = '1';
}
ans[len] = '\0';
reserve(ans);
return ans;
}