题目:
Given two binary strings, return their sum (also a binary string).
The input strings are both non-empty and contains only characters 1
or 0
.
Example 1:
Input: a = "11", b = "1"
Output: "100"
Example 2:
Input: a = "1010", b = "1011"
Output: "10101"
这道题也是,乍一看很简单,就是把两个二进制的字符串相加得到结果,然而自己还是憋了半天写不出来啊我好菜啊。
参考了大佬们的思路,发现其实也很简单啊为什么自己之前想不到呢,不解。大概是之前的思路过于局限于“如果有进位那么blablabla,如果没有进位那么blablabla),而没有从整体上去思考这一位要怎么得到。并且遍历的方式刚开始的思维也太局限了,一直只想着只有一个循环变量,于是还得计算谁长谁短和每一位的表示方式,光是抠细节就很烦人。进位的异或倒是自己在纸上比比划划出来了。
这道题的思路就在于两个字符串都同时从后向前遍历,设置两个循环变量,遍历到所有的都结束时停止。这时候可能会想如果有一个字符串遍历完了怎么办,其实这个问题可以放到loop里解决,遍历完的(也就是它的循环变量<0的)就直接当它为0就好,一条语句就可以解决每一位的表示方式的问题。接下来的关键点就在于如何表示carry和这一个bit,bit有两种表示方法,一种是直接采用a、b和carry进行异或,另一种就是(a + b + carry) % 2;carry的话就只有一种表示方法,就是( a + b + carry)取第二位,但是这个取法有很多种,比如直接除2(/2)、向右移1位(>>1)、是否大于等于2(>=2)等等。最后,按照我前面说的这种遍历方式,也就是没有把carry放在循环条件判断中的情况下,最后需要额外判断carry是否为1,如果有进位的话还需要在整个字符串前面补1,没有的话直接返回字符串就好。代码如下,运行时间0ms:
class Solution {
public:
string addBinary(string a, string b) {
string result = "";
int carry = 0;
for (int i = a.size() - 1, j = b.size() - 1; i >= 0 || j >= 0; i--, j--) {
int a_bit = (i >= 0 && a[i] == '1') ? 1 : 0;
int b_bit = (j >= 0 && b[j] == '1') ? 1 : 0;
result = char((a_bit ^ b_bit ^ carry) + '0') + result;
carry = (a_bit + b_bit + carry) / 2;
}
return carry ? '1' + result : result;
}
};
如果不希望在最后的时候额外判断carry,那么也可以把carry加入判断条件,代码如下:
class Solution {
public:
string addBinary(string a, string b) {
string result = "";
int carry = 0;
int i = a.size() - 1, j = b.size() - 1;
while (i >= 0 || j >= 0 || carry == 1) {
int a_bit = (i >= 0 && a[i] == '1') ? 1 : 0;
int b_bit = (j >= 0 && b[j] == '1') ? 1 : 0;
result = char((a_bit ^ b_bit ^ carry) + '0') + result;
carry = (a_bit + b_bit + carry) / 2;
i--;
j--;
}
return result;
}
};
看到一个comments中有人提出result = xx + result这一句每次都会重新复制一遍result,导致时间复杂度飙升为O(n^2),所以可以每次都加在后面(即result += xx),最后再通过reverse来获得最终的结果,这样就可以保证在O(n)的情况下完成,嗯,这点真的是完全没想到,有点收获。