java solution
class Solution {public String addBinary(String a, String b) {StringBuilder result = new StringBuilder();//首先设置2个指针, 从右往左处理int i = a.length() - 1;int j = b.length() - 1;int carry = 0; //设置进位标志位//从2个字符串的末尾向前遍历while(i >= 0 || j >= 0 || carry != 0) {//先分别获取2个字符串当前位置的十进制数值int digitA = (i >= 0) ? a.charAt(i--) - '0' : 0; //这里注意需要自减int digitB = (j >= 0) ? b.charAt(j--) - '0' : 0;int sum = digitA + digitB + carry; //这里是十进制加法//在结果中append当前位的计算结果result.append(sum % 2);carry = sum / 2;}return result.reverse().toString();}
}
当然可以!我们来一步一步详细剖析这段 Java 代码的算法思想和实现原理:
✅ 题目本质
这道题要求我们实现「两个二进制字符串相加」,就像我们在纸上做十进制加法一样,不过这次是二进制的:
位数 | 0 + 0 = 0 |
---|---|
0 + 1 = 1 | |
1 + 0 = 1 | |
1 + 1 = 10(结果是 0,进位 1) | |
1 + 1 + 1 = 11(结果是 1,进位 1) |
🔍 代码结构逐行解释
public class Solution {
定义一个类 Solution
,这是 LeetCode 的标准题解结构。
public String addBinary(String a, String b) {
定义一个公开方法 addBinary
,接受两个二进制字符串 a
和 b
,返回它们的和(也是字符串形式的二进制)。
StringBuilder result = new StringBuilder();
我们用 StringBuilder
来构造最终结果字符串,原因是字符串拼接性能较差,而 StringBuilder
更高效。
int i = a.length() - 1;int j = b.length() - 1;
定义两个指针 i
和 j
,分别指向字符串 a
和 b
的末尾。因为加法是从个位(末尾)开始做的。
int carry = 0;
初始化进位变量 carry
为 0。这个变量用来处理每一位相加后是否有进位。
🔁 核心 while 循环逻辑
while (i >= 0 || j >= 0 || carry != 0) {
只要:
a
或b
还有没处理完的位,或者- 还有进位没有处理
就继续加。
int digitA = (i >= 0) ? a.charAt(i--) - '0' : 0;int digitB = (j >= 0) ? b.charAt(j--) - '0' : 0;
- 如果
i
或j
没越界,就取出当前字符,并减去'0'
得到整数(例如 ‘1’ - ‘0’ = 1)。 - 如果已经越界(即字符串长度不一样),就当作
0
处理。 - 然后每次用
i--
和j--
向前移动一位。
int sum = digitA + digitB + carry;
计算当前位的加法总和(包括进位)。
result.append(sum % 2);
把当前位的结果添加到结果字符串中。二进制相加的结果只有 0 或 1,所以取模即可。
carry = sum / 2;
计算进位:比如 1+1=2,carry = 1
,sum % 2 = 0
;比如 1+1+1=3,carry = 1
,sum % 2 = 1
🔁 退出循环后
return result.reverse().toString();
注意:我们是从低位到高位(右向左)构建的字符串,最后要用 .reverse()
翻转回来。
🧠 算法思想总结
- 双指针思想:从两个字符串的末尾向前遍历。
- 模拟竖式加法:一位一位加,处理进位。
- 边界处理:长度不等时自动补零,进位单独判断。
- 空间优化:用
StringBuilder
构建字符串效率高。
🕐 时间复杂度分析
- 时间复杂度:
O(max(m, n))
,m 和 n 是字符串 a 和 b 的长度。 - 空间复杂度:
O(max(m, n))
,用于存储结果字符串。
如果你想,我也可以加图示模拟演示某个例子,比如 a = "1010"
, b = "1011"
是怎么一步步算出 "10101"
的。需要我补上吗?