(算法練習)二進制求和

力扣上面的算法題目:(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的使用.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章