對於比較小的數字,作運算能夠直接使用編程語言提供的運算符,可是若是相乘的兩個因數很是大,語言提供的數據類型可能就會溢出。一種替代方案就是,運算數以字符串的形式輸入,而後模仿咱們小學學習的乘法算術過程計算出結果,而且也用字符串表示。git
須要注意的是,num1
和 num2
能夠很是長,因此不能夠把他們直接轉成整型而後運算,惟一的思路就是模仿咱們手算乘法。算法
好比說咱們手算 123 × 45
,應該會這樣計算:編程
計算 123 × 5
,再計算 123 × 4
,最後錯一位相加。這個流程恐怕小學生均可以熟練完成,可是你是否能把這個運算過程進一步機械化,寫成一套算法指令讓沒有任何智商的計算機來執行呢?數組
PS:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,所有發佈在 labuladong的算法小抄,持續更新。建議收藏,按照個人文章順序刷題,掌握各類算法套路後投再入題海就如魚得水了。編程語言
你看這個簡單過程,其中涉及乘法進位,涉及錯位相加,還涉及加法進位;並且還有一些不易察覺的問題,好比說兩位數乘以兩位數,結果多是四位數,也多是三位數,你怎麼想出一個標準化的處理方式?這就是算法的魅力,若是沒有計算機思惟,簡單的問題可能都沒辦法自動化處理。ide
首先,咱們這種手算方式仍是太「高級」了,咱們要再「低級」一點,123 × 5
和 123 × 4
的過程還能夠進一步分解,最後再相加:學習
如今 123
並不大,若是是個很大的數字的話,是沒法直接計算乘積的。咱們能夠用一個數組在底下接收相加結果:spa
整個計算過程大概是這樣,有兩個指針 i,j
在 num1
和 num2
上游走,計算乘積,同時將乘積疊加到 res
的正確位置:翻譯
如今還有一個關鍵問題,如何將乘積疊加到 res
的正確位置,或者說,如何經過 i,j
計算 res
的對應索引呢?3d
其實,細心觀察以後就發現,num1[i]
和 num2[j]
的乘積對應的就是 res[i+j]
和 res[i+j+1]
這兩個位置。
明白了這一點,就能夠用代碼模仿出這個計算過程了:
string multiply(string num1, string num2) { int m = num1.size(), n = num2.size(); // 結果最多爲 m + n 位數 vector<int> res(m + n, 0); // 從個位數開始逐位相乘 for (int i = m - 1; i >= 0; i--) for (int j = n - 1; j >= 0; j--) { int mul = (num1[i]-'0') * (num2[j]-'0'); // 乘積在 res 對應的索引位置 int p1 = i + j, p2 = i + j + 1; // 疊加到 res 上 int sum = mul + res[p2]; res[p2] = sum % 10; res[p1] += sum / 10; } // 結果前綴可能存的 0(未使用的位) int i = 0; while (i < res.size() && res[i] == 0) i++; // 將計算結果轉化成字符串 string str; for (; i < res.size(); i++) str.push_back('0' + res[i]); return str.size() == 0 ? "0" : str; }
至此,字符串乘法算法就完成了。
PS:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,所有發佈在 labuladong的算法小抄,持續更新。建議收藏,按照個人文章順序刷題,掌握各類算法套路後投再入題海就如魚得水了。
總結一下,咱們習覺得常的一些思惟方式,在計算機看來是很是難以作到的。好比說咱們習慣的算術流程並不複雜,可是若是讓你再進一步,翻譯成代碼邏輯,並不簡單。算法須要將計算流程再簡化,經過邊算邊疊加的方式來獲得結果。
俗話教育咱們,不要陷入思惟定式,不要程序化,要發散思惟,要創新。但我以爲程序化並非壞事,能夠大幅提升效率,減少失誤率。算法不就是一套程序化的思惟嗎,只有程序化才能讓計算機幫助咱們解決複雜問題呀!
也許算法就是一種尋找思惟定式的思惟吧,但願本文對你有幫助。
_____________