大數相乘

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

分析:數組

因爲數字沒法用一個整形變量存儲,很天然的想到用字符串來表示一串數字。而後按照乘法的運算規則,用一個乘數的每一位乘以另外一個乘數,而後將全部中間結果按正確位置相加獲得最終結果。能夠分析得出若是乘數爲A和B,A的位數爲m,B的位數爲n,則乘積結果爲m+n-1位(最高位無進位)或m+n位(最高位有進位)。測試

所以能夠分配一個m+n的輔存來存儲最終結果。爲了節約空間,全部的中間結果直接在m+n的輔存上進行累加。最後爲了更符合咱們的乘法運算邏輯,能夠講數字逆序存儲,這樣數字的低位就在數組的低下標位置,進行累加時肯定下標位置較容易些。code

先對數組逆序字符串

void reverseOrder(char* str, int p, int q)
{
    char temp;
    while(p < q)
    {
        temp = str[p];
        str[p] = str[q];
        str[q] = temp;
        p ++;
        q --;
    }
}
char* multiLargeNum(char* A, char* B)
{
    int m = strlen(A);
    int n = strlen(B);
    char* result = new char[m+n+1];
    memset(result, '0', m+n);
    result[m+n] = '\0';
    reverseOrder(A, 0, m-1);
    reverseOrder(B, 0, n-1);

    int multiFlag; // 乘積進位
    int addFlag;   // 加法進位
    for(int i=0; i <= n-1; i++) // B的每一位
    {
        multiFlag = 0;
        addFlag = 0;
        for(int j=0; j <= m-1; j++) // A的每一位
        {
            // '0' - 48 = 0
            int temp1 = (A[j] - 48) * (B[i] - 48) + multiFlag;
            multiFlag = temp1 / 10;
            temp1 = temp1 % 10;
            int temp2 = (result[i+j] - 48) + temp1 + addFlag;
            addFlag = temp2 / 10;
            result[i+j] = temp2 % 10 + 48; 
        }
        result[i + m] += multiFlag + addFlag;
    }
    reverseOrder(result, 0, m+n-1); // 逆序回來

    return result;
}

測試:class

int main()
{
    char A[] = "962346239843253528686293234124";
    char B[] = "93459382645998213649236498";
    char *res = multiLargeNum(A, B);
    if(res[0] != 48)
        printf("%c", res[0]);
    printf("%s", res+1);
    delete [] res;
    return 0;
}

時間複雜度分析:變量

3個逆序操做的時間分別爲O(n)、O(m)、O(m+n),雙重循環的時間複雜度爲O(mn),則總的時間複雜度爲O(mn + (m+n)),一般m+n << mn,所以可近似認爲爲O(mn)。並且,逆序操做只是爲了思考更容易,徹底能夠去掉。循環

空間複雜度爲O(m+n)數據

相關文章
相關標籤/搜索