力扣上面的算法題目:(https://leetcode-cn.com/problems/add-binary/)
給定兩個二進制字符串,返回他們的和(用二進制表示)。
輸入爲非空字符串且只包含數字 1 和 0。
示例 1:
輸入: a = "11", b = "1"
輸出: "100"
示例 2:輸入: a = "1010", b = "1011"
輸出: "10101"來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/add-binary
主要考察的知識點:
1.當前字符的 ASCII 值減去 '0' 的 ASCII 值,相當於將這個字符轉換成數值
2.StringBuilder
與 StringBuffer
的區別
3.字符翻轉的方法 reverse();
4.時間複雜度的計算
實現思路:
整體思路是將兩個字符串較短的用 00 補齊,使得兩個字符串長度一致,然後從末尾進行遍歷計算,得到最終結果。
本題解中大致思路與上述一致,但由於字符串操作原因,不確定最後的結果是否會多出一位進位,所以會有 2 種處理方式:
第一種,在進行計算時直接拼接字符串,會得到一個反向字符,需要最後再進行翻轉
第二種,按照位置給結果字符賦值,最後如果有進位,則在前方進行字符串拼接添加進位
方案一:相關代碼 (ps 由於Asscii 的知識點是盲點,我也是一句句敲的,一邊寫一邊理解思路,加上備註)
class Solution {
public String addBinary(String a, String b) {
int aLen = a.length();
int bLen = b.length();
int maxLen = Math.max(aLen,bLen);
//字符串進行翻轉
StringBuilder sbA = new StringBuilder(a).reverse();
StringBuilder sbB = new StringBuilder(b).reverse();
//讓兩個字符串補齊成一個長度,翻轉過後前置位補0
while(sbA.length() < maxLen){
sbA.append("0");
}
while(sbB.length() < maxLen){
sbB.append("0");
}
StringBuilder res = new StringBuilder();
//進位的標誌位, 默認是0
int carry = 0;
//知識點:當前字符的 ASCII 值減去 '0' 的 ASCII 值,相當於將這個字符轉換成數值
int num1;
int num2;
for(int i=0; i < maxLen; i++){
num1 = sbA.charAt(i) - '0';
num2 = sbB.charAt(i) - '0';
if(carry + num1 + num2 > 1){
//1+1的情況,在二進制下 需要減去2
res.append(carry + num1 + num2 - 2);
//表示 需要進位,改變標誌位
carry = 1;
}else{
res.append(carry + num1 + num2);
carry = 0;
}
}
//對於最高位 需要增加位數,如果存在進位的情況
if(carry == 1){
res.append("1");
}
//最後再翻轉一次,爲開始補位的時候就是翻轉後的
return res.reverse().toString();
}
}
方案二:相關代碼 (ps 我也是一句句敲的,一邊寫一邊理解思路,加上備註)
上面的代碼“翻轉”了兩次,顯得有點囉嗦,我們可以使用兩個指針,分別從字符串的末尾開始向前遍歷,同時在借用 StringBuilder 對象的 insert 方法,從右向左依次得出計算結果,就真的非常接近我們手寫“豎式加法”的過程了。下面是參考代碼(摘錄自題解)
private String doAddWithInsert(String a, String b){
int i = a.length() - 1;
int j = b.length() - 1;
//這個是結果: 可變的字符序列對象
StringBuilder res = new StringBuilder();
int curSum;
//進位的標誌位
int carry = 0;
while(i >=0 || j >=0){
curSum = carry;
//當前位置的a的i位和 b 的j 位,都是末位進行相加
if(i >= 0){
curSum += a.charAt(i) - '0';
i--;
}
if(j >= 0){
curSum += b.charAt(j) - '0';
j--;
}
//判斷是否需要進位
if(curSum > 1){
//1+1的情況,在二進制下 需要減去2,有進位
curSum -= 2;
carry = 1;
}else{
carry = 0;
}
// 只寫結果的值,進位作爲下一輪的初始值
res.insert(0, curSum);
}
if(carry == 1){
res.insert(0, 1);
}
return res.toString();
}
方案一可能好理解一些,但是方案二更加符合 豎加的 思路,主要點我覺得是 insert的使用.