力扣解题-67. 二进制求和
给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。
示例 1:
输入:a = "11", b = "1"
输出:"100"
示例 2:
输入:a = "1010", b = "1011"
输出:"10101"
提示:
1 <= a.length, b.length <= 10⁴
a 和 b 仅由字符 '0' 或 '1' 组成
字符串如果不是 "0" ,就不含前导零
Related Topics
位运算、数学、字符串、模拟
第一次解答
解题思路
核心方法:字符串模拟二进制加法,先将两个字符串补零对齐长度,再从低位到高位逐位相加,维护进位标志,最终拼接结果字符串。完全模拟人工二进制加法的过程,逻辑直观、易于理解。
核心逻辑拆解
二进制求和的核心是逐位相加 + 处理进位,遵循规则:
- 0+0=0,无进位
- 0+1=1,无进位
- 1+1=0,进位1
- 若有进位,参与下一位计算
- 遍历结束仍有进位,需在最前面补1
具体执行逻辑
- 对齐补零
- 计算两个字符串的最大长度,调用
addZero方法给短字符串前面补0,让两个字符串长度完全一致,方便逐位计算。
- 计算两个字符串的最大长度,调用
- 逐位相加
- 从**最后一位(最低位)**向前遍历;
- 根据当前位的两个数字 + 进位
isUp,判断当前位结果和新的进位; - 将计算出的当前位拼接在结果字符串的最前面。
- 最终进位处理
- 遍历完成后,如果仍有进位
isUp=true,需要在结果最前面加一个1。
- 遍历完成后,如果仍有进位
- 返回结果
关键细节说明
- 补零对齐:保证两个字符串从右到左每一位都能正确对应,避免越界;
- 进位标志
isUp:布尔类型表示是否需要进位,简化判断逻辑; - 字符串拼接:每次将新位拼接到结果前面,符合从低位到高位的计算顺序;
- 边界处理 :最高位相加后仍有进位时,必须额外添加
1。
性能说明
- 时间复杂度:O(max(len(a), len(b))),只需一次遍历;
- 空间复杂度:O(max(len(a), len(b))),存储结果与补零后的字符串;
- 优点:逻辑非常直观,完全模拟人工计算,新手极易理解;
- 缺点:频繁使用
String拼接("1"+result),在字符串很长时效率较低。
java
class Solution {
public String addBinary(String a, String b) {
int aLength=a.length();
int bLength=b.length();
int maxLength=Math.max(aLength,bLength);
a=addZero(a,maxLength);
b=addZero(b,maxLength);
String result="";
boolean isUp=false;
for(int i=maxLength-1;i>=0;i--){
char ac=a.charAt(i);
char bc=b.charAt(i);
if(isUp){
if(ac=='1'&& bc=='1'){
result="1"+result;
isUp=true;
}else if(ac=='0' && bc=='0'){
result="1"+result;
isUp=false;
}else {
result="0"+result;
isUp=isUp;
}
}else {
if(ac=='1'&& bc=='1'){
result="0"+result;
isUp=true;
}else if(ac=='0' && bc=='0'){
result="0"+result;
isUp=false;
}else {
result="1"+result;
isUp=false;
}
}
}
if(isUp){
result="1"+result;
}
return result;
}
public String addZero(String s, int length) {
int originalLength = s.length();
if (originalLength < length) {
for (int i = 0; i < length - originalLength; i++) {
s = "0" + s;
}
}
return s;
}
}
示例解答
解题思路
解法1:标准高效模拟法(最优推荐,无需补零 + StringBuilder)
核心改进点:
- 不补零:直接用双指针从后往前遍历,短字符串遍历完后用0代替;
- 使用StringBuilder:避免String频繁拼接,效率大幅提升;
- 数学计算代替大量if-else:代码更简洁、通用、易维护。
代码实现
java
public String addBinary(String a, String b) {
StringBuilder sb = new StringBuilder();
int i = a.length() - 1;
int j = b.length() - 1;
int carry = 0; // 用数字表示进位,更简洁
while (i >= 0 || j >= 0 || carry > 0) {
// 取出当前位数字,没有则为0
int numA = (i >= 0) ? a.charAt(i--) - '0' : 0;
int numB = (j >= 0) ? b.charAt(j--) - '0' : 0;
int sum = numA + numB + carry;
carry = sum / 2; // 新的进位
sb.append(sum % 2); // 当前位结果
}
// 最后反转得到正确顺序
return sb.reverse().toString();
}
核心逻辑说明
- 双指针从后往前 :
i指向a末尾,j指向b末尾; - 数字计算 :
sum = 位a + 位b + 进位- 当前位 =
sum % 2 - 新进位 =
sum / 2
- StringBuilder高效拼接:先追加到尾部,最后统一反转;
- 无需补零、无复杂if-else,代码极简高效。
性能说明
- 时间复杂度:O(max(len(a), len(b)))
- 空间复杂度:O(max(len(a), len(b)))
- 优势:工业级标准写法,高效、简洁、无冗余操作,面试首选。
解法2:位运算解法(数学进阶版)
核心方法:使用异或求无进位和 + 与运算求进位,纯位运算实现二进制加法。
代码实现
java
public String addBinary(String a, String b) {
int x = Integer.parseInt(a, 2);
int y = Integer.parseInt(b, 2);
while (y != 0) {
int carry = (x & y) << 1;
x = x ^ y;
y = carry;
}
return Integer.toBinaryString(x);
}
⚠️ 注意 :该方法只适用于字符串长度不超过32位的场景,题目中长度可达10⁴,会溢出,不能AC,仅作学习理解。
总结
- 你的原解法:模拟思路完美、逻辑清晰,适合理解二进制加法原理;
- 推荐高效版(解法1) :
- 不用补零、不用大量if-else
- 使用StringBuilder高效拼接
- 数学计算简洁通用
- 面试/比赛标准写法
- 核心技巧 :
- 二进制求和 = 逐位相加 + 进位处理
- 高效拼接一定要用
StringBuilder - 从后往前遍历无需补零对齐