大數相乘

近期看的算法比較雜,在博客上簡單記錄一下吧。大數相乘貌似在不少公司的面試中都有問過。面試

問題描述:算法

輸入兩個整數,要求輸出這兩個數的乘積。輸入的數字可能超過計算機內整形數據的存儲範圍。spa

乘數A和B分別存放在字符串裏,輸出結果也存放在字符串中。code

問題分析:blog

首先,考慮相似0000000123456789這樣數字輸入,爲了不沒必要要的計算,能夠對輸入字符串進行預處理preProcess,把前綴爲0的字符串簡化爲從第一個不爲零的數字開始的字符串。ip

其次,考慮輸出字符串的長度,假設A的長度爲a,B的長度爲b,則二者相乘的長度爲a + b - 1或者a + b。字符串

第三,注意char和int之間的相互轉化,char c轉int a的方法:a = c - '0'或 a = c - 48,int a轉char c的方法:c = (char) (a + 48)博客

而後,每次用一個數的一位與另外一個數從低至高依次相乘,並與結果上的該位相加,動態更新結果。這個過程須要有addFlag和multiFlag來記錄上次運算的加法進位和乘法進位。class

最後,一樣使用preProcess將結果最高位的0去掉。test

public class Multiple {
    public String multiple(String A, String B) {
        String A1 = preProcess(A);
        String B1 = preProcess(B);
        char[] c1 = A1.toCharArray();
        char[] c2 = B1.toCharArray();
        char[] rst = new char[c1.length + c2.length];
        for (int i = 0; i < rst.length; i++) {
            rst[i] = '0';
        }
        reverse(c1, 0, c1.length - 1);
        reverse(c2, 0, c2.length - 1);
        for (int i = 0; i < c1.length; i++) {
            int addFlag = 0;
            int multiFlag = 0;
            for (int j = 0; j < c2.length; j++) {
                int temp1 = (c1[i] - 48) * (c2[j] - 48) + multiFlag;
                multiFlag = temp1 / 10;
                temp1 = temp1 % 10;
                int temp2 = rst[i + j] - 48 + temp1 + addFlag;
                addFlag = temp2 / 10;
                rst[i + j] = (char) (temp2 % 10 + 48);
            }
            rst[i + c2.length] = (char) (addFlag + multiFlag + 48);
        }
        reverse(rst, 0, rst.length - 1);
        return preProcess(new String(rst));        
    }
    public void reverse(char[] c, int start, int end) {
        while (start < end) {
            char temp = c[start];
            c[start] = c[end];
            c[end] = temp;
            start++;
            end--;
        }
    }
    public String preProcess(String s) {
        char[] c = s.toCharArray();
        int i = 0;
        while (i < c.length) {
            if (c[i] == '0') {
                i++;
                continue;
            } else {
                break;
            }
        }
        if (i == c.length) {
            return new String("0");
        }
        return new String(c, i, c.length - i);
    }
}

test case試過了「0000」*「00」,「999999」*「99」,「0011」*「01」這樣的邊界case,都沒有問題。

這裏的乘法默認是非負數相乘,若爲負數相乘,只須要預先判斷第一位,最後在結果加上相應符號便可。

相關文章
相關標籤/搜索