力扣#43 字串相乘(C++)

Raymond_YP發表於2020-09-26

題目如下:官網oj

在這裡插入圖片描述
  題目意思就是讓我們自己去模擬乘法,因為兩個相乘的數字很大,long long型別都儲存不下,只能拿字串模擬乘法的過程得到答案。
  演算法簡述:首先考慮特殊情況,當num1或者num2為0的時候,返回0。考慮特殊情況之後把num1和num2反轉過來,令num1[0]即num1的低位的位權最低,num1[num1.length()-1]即num1的高位的位權最高,這樣方便我們計算求解。我們在做乘法的時候,比如1234 * 567的時候,將567的每一位與1234相乘之後,再錯位相加得到答案。如下圖 1234 * 567 :
在這裡插入圖片描述
利用上述思想,可以編寫兩層for迴圈來模擬,接下來要考慮進位問題,當相乘的結果大於10就會產生進位,進到下一位,定義一個int變數carry來存放上述進位資訊,容易得到這樣的程式碼:

int tmp = (num1[i] - '0') * (num2[j] - '0') + carry+ans[i+j]-'0';
carry = tmp / 10;
ans[i + j] = tmp % 10+'0';

在固定一次b與a進行一次乘法之後,還可能產生進位,此時已經跳出了b的迴圈,這時候的進位應進到相應的位上,而不能丟棄,如下:

if (carry) {
		ans[i + num2.length()] += carry;
		carry = 0;
}

所有的計算結束之後,我們還需要把答案reverse一下,因為我們一開始把num1和num2都reverse了,還記得嘛。要reverse,就需要傳入開頭和結尾的迭代器,這時候就需要計算得到的答案的長度,具體程式碼見如下程式碼:

class Solution {
public:
    string multiply(string num1, string num2) {
    	//考慮特殊情況
        if(num1=="0"||num2=="0")
            return string("0");

		//ans長度230肯定夠了
        string ans(230, '0');
        //反轉數字
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());

        int carry = 0, len = num1.length() + num2.length() - 1;
        //模擬乘法
        for (int i = 0; i < num1.length(); i++) {
            for (int j = 0; j < num2.length(); j++) {
                int tmp = (num1[i] - '0') * (num2[j] - '0') + carry+ans[i+j]-'0';
                //進位
                carry = tmp / 10;
                ans[i + j] = tmp % 10+'0';
            }
            if (carry) {
            	//b的一位和a的最高位相乘還有進位,特殊處理一下
                ans[i + num2.length()] += carry;
                carry = 0;
                //整個答案的最高位還有進位,那麼ans的長度加1
                if (i == num1.length() - 1)
                    len++;
            }
        }
        //反轉ans
        reverse(ans.begin(), ans.begin() + len);
        //返回子串也就是最終答案
        return ans.substr(0, len);
    }
};

相關文章