题目描述#
哎呀,咱来翻译下题面~给你两个用字符串表示的二进制数 a 和 b,返回它们相加之后、同样用二进制字符串表示的结果。
输入只含 '0' 和 '1',而且除了 "0" 本身之外,开头不会有多余的前导零。
思路#
咱第一眼看,这题别被"二进制"三个字唬住——它本质就是小学的竖式加法,只不过逢二进一而已。
既然是竖式,那就得从**最低位(字符串末尾)往最高位(开头)**逐位相加。咱用两个指针 i、j 分别指向 a、b 的末尾,再拿一个 carry 记进位。
每一轮咱把三样东西加起来:进位 carry、当前 a[i]、当前 b[j]。注意字符 '0'/'1' 要先减掉 '0' 才变成真正的数字 0/1。加完得到 sum 之后:
- 当前位的结果就是
sum % 2(逢二进一,所以对 2 取余); - 新的进位就是
sum / 2(整除 2,要么是 0 要么是 1)。
循环什么时候停?只要 a 还没走完、b 还没走完、或者进位还没处理干净,就得继续。那个 carry > 0 的条件特别关键——比如 "1" + "1" 最后会多出一个最高位的 1,要是漏了它结果就少一位啦。
因为咱是从低位往高位算的,而结果字符串要从高位往低位读,所以每算出一位就把它拼到答案最前面(ans = 新位 + ans)。本姑娘提醒一句:这样拼天然就把顺序摆正了,不用最后再反转~
照片当然不是现实,但只要一位一位拍够了,拼起来就是完整的那张图——加法也是,一位一位进上去,答案自然成形。
知识边界#
- 字符与数字的转换:
a[i] - '0'把字符'1'转成整数1,反过来byte(x) + '0'把数字转回字符。漏减'0'会直接拿到 ASCII 码('1'是 49),结果全错——这点容易踩坑哦。 - 逢二进一:
sum % 2取当前位,sum / 2取进位。换成十进制加法就是% 10和/ 10,一套模板通用。 - 进位的收尾:循环条件里的
carry > 0不能省,否则最高位的进位会丢失(如"11" + "1")。 - 字符串前插:
ans = string(...) + ans把新位拼到最前,省去最后反转。不过 Go 里字符串是不可变的,这种前插每次都会重新分配,数据量大时换[]byte倒序填充 + 反转会更高效——本题数据小,这么写够清楚。 string(byte)的坑:这里byte(sum%2)+'0'已经是一个合法的 ASCII 字符字节,再用string(...)转成单字符字符串是 OK 的;别误用成string(数字)(那会按 Unicode 码点转,结果不对)。
代码#
下面这版咱一行没动,逻辑就是上面那套竖式:
func addBinary(a string, b string) string {
i := len(a) - 1
j := len(b) - 1
carry := 0
ans := ""
for i >= 0 || j >= 0 || carry > 0 {
sum := carry
if i >= 0 {
sum += int(a[i] - '0')
i--
}
if j >= 0 {
sum += int(b[j] - '0')
j--
}
// 当前位
ans = string(byte(sum%2)+'0') + ans
// 进位
carry = sum / 2
}
return ans
}