题目:
给你两个二进制字符串,返回它们的和(用二进制表示)。
输入为非空字符串且只包含数字 1
和 0
。
示例1:
输入: a = "11", b = "1"
输出: "100"
示例2:
输入: a = "1010", b = "1011"
输出: "10101"
分析:
其实就是两个二进制数的加法运算,两个二进制数相加,首先设置一个进位标识符flag,初始值设置0。从低位到高位开始相加:
1、对应位置相加,然后再加上flag,三者之和设置为temp_sum,然后结果值的当前位为temp_sum%2,flag = temp_sum/2
2、进行遍历二进制字符串的时候,因为需要从低位开始运算,而二进制数的低位之于字符串对应的位置,是字符串的索引高位,所以解决方法就有两个:
(1)设置两个游标变量,初始值为a、b两个字符串的长度减去1,然后开始遍历,没完成一次,游标变量就自减运算一次
(2)将两个二进制数字符串逆置一下,然后索引低位就和二进制低位对应上了,最后再将结果倒置一下就可以了
3、遍历进行的条件是,a的游标变量的值要在0-a.length这个范围内 或者 b的游标变量的值要在0-b.length这个范围内 或者 flag==1
实现代码1:
public String addBinary(String a, String b) {
StringBuilder sa = new StringBuilder(a).reverse();
StringBuilder sb = new StringBuilder(b).reverse();
StringBuilder sc = new StringBuilder();
int i = 0;
int flag = 0;
while (i < sa.length() && i < sb.length()){
if (sa.charAt(i) == '1' && sb.charAt(i) == '1'){
if (flag == 0){
sc.append(0);
}else {
sc.append(1);
}
flag = 1;
}else if (sa.charAt(i) == '1' || sb.charAt(i) == '1'){
if (flag == 1){
sc.append(0);
flag = 1;
}else {
sc.append(1);
}
}else {
if (flag == 1){
sc.append(1);
}else {
sc.append(0);
}
flag = 0;
}
i++;
}
while (i < sa.length()){
if (flag == 1){
if (sa.charAt(i) == '1'){
sc.append(0);
flag = 1;
}else {
sc.append(1);
flag = 0;
}
}else{
if (sa.charAt(i) == '1'){
sc.append(1);
}else {
sc.append(0);
}
}
i++;
}
while (i < sb.length()){
if (flag == 1){
if (sb.charAt(i) == '1'){
sc.append(0);
flag = 1;
}else {
sc.append(1);
flag = 0;
}
}else{
if (sb.charAt(i) == '1'){
sc.append(1);
}else {
sc.append(0);
}
}
i++;
}
if (flag == 1){
sc.append(1);
}
return sc.reverse().toString();
}
可以优化一下,上面的代码太麻烦了:
public String addBinary(String a, String b) {
int i = a.length() - 1, j = b.length() - 1, carry = 0;
StringBuilder str = new StringBuilder();
while (carry == 1 || i >= 0 || j >= 0) {
if (i >= 0 && a.charAt(i--) == '1') {
carry++;
}
if (j >= 0 && b.charAt(j--) == '1') {
carry++;
}
str.append(carry % 2);
carry /= 2;
}
return str.reverse().toString();
}
这段代码参考自大神CyC2018。