Leetcode基礎篇30天30題系列之數組:模擬計算法

數組:加一

題幹:

給定一個由整數組成的非空數組所表示的非負整數,在該數的基礎上加一。

最高位數字存放在數組的首位, 數組中每個元素只存儲一個數字。

你可以假設除了整數 0 之外,這個整數不會以零開頭。

參考樣例:

示例 1:

輸入: [1,2,3]

輸出: [1,2,4]

解釋: 輸入數組表示數字 123。

示例 2:

輸入: [4,3,2,1]

輸出: [4,3,2,2]

解釋: 輸入數組表示數字 4321。

這道題是一道數組的基礎題,其本質是一道模擬計算題。

這道題有一定的工程應用意義,大家都知道,計算機的浮點數運算有誤差,究其細節有相當數量的開發者卻往往不求甚解。請看:

做開發的朋友都知道計算機在程序處理中,都是將十進制數轉成二進制數進行運算的。對於這種轉化,其方法就是除2逆向取餘法,例如:

十進制數13轉成二進制的方法就是

                     

轉化成數學表達式就是(13) ₁₀=(1101) ₂

對於十進制小數轉化成二進制小數使用的方法是乘2正向取整法,比如十進制的0.75

即(0.75) ₁₀=(0.11) ₂

如果,我們考慮下將十進制的0.6轉化成二進制呢?如果依然使用乘二正向取整法會發生什麼呢?

如果從數學上講,(0.75) ₁₀=(0.1001) ₂

爲什麼會出現這種循環表示呢?因爲數學上有證明,十進制表示法與二進制表示法,僅僅在整數範圍內纔有明確的對應的關係,而小數部分是做不到的。因此,在採用二進制運算上,計算機的數值求解是有缺陷的。

意識到這一點,我們就會問那麼是不是我們現在和小數點相關的運行都是不可靠的呢?顯然不可能,最常見的就是我們的金融活動。大凡和交易有關的數據,那是一個數字都不能出錯的,那麼他們背後的計算過程又是如何保證的呢?

答案就是模擬計算。

在小學數學課本上就教過這樣的案例:123.4+5.67,我們來看,加數與被加數的位數並不相同,小學老師在教學中一定會強調對齊小數點,其過程如下:

這個在計算機中有一個術語叫做對階。所謂階就是進制,十進制的階就是10,二進制的階就是2,具體的數學表達就是

123.4 = 1×10²+2×10¹+3×100+4×10-¹

5.67=5×100+6×10-¹+7×10-²

我們知道計算機的整數運算是沒有缺陷的,如果我們這樣做,是不是就可以達到精確求解的目的了?

123.4+5.67=(12340+567)×10-²=12907×10-²=129.07

這就是精度計算中的常用的計算思想,這也是爲什麼在以Java爲核心語言中做交易系統中,金額通常不用float,double而用decimal類型的原因。

明白了這個知識,我們就知道了這個看似普通的題目,其實是企業開發商用軟件中的一個現實問題。那麼,在現實計算中,人們又是如何來處理上述的對階、運算的過程呢?答案就是數組。我們用數組來模擬每一位,然後用小學數學課本教授的方法,手工計算出就可以了。

下面回到這個題目:題目的函數簽名是這樣的:vector<int> plusOne(vector<int>& digits)

傳入的參數是digits,是一個整型的向量,其位數按照角標升序排列,即角標0對應的是數字的最高位,最後一位表示的數字的最低位,比如參考樣例:[1,2,3],他表示的是十進制123,角標0對應的是百位1,角標2對應的是個位3.模擬十進制計算的過程,就是逢10進位,這道題我們首先要找到最低位,如果最低位不是9,直接取出角標對應的數值加1即可,如果是數字的9的話,那麼直接將其改爲0,並向其上一位角標對應的數字加1.需要注意的細節是,如果這個數字恰好是[9,9,9],那麼返回值應當增加1位得到[1,0,0,0]。爲了方便編程,我們從最後一位開始。代碼如下:

1 vector<int> plusOne(vector<int>& digits) {

2        int n = digits.size();

3        for(int i=n-1;i>=0;i--){

4            if(digits[i] == 9)

5                digits[i] =0;

6            else {

7                digits[i]++;

8                return digits;

9            }            

10        }

11        digits[0] =1;

12        digits.push_back(0);

13        return digits;

14 }

第2行,首先獲得當前向量digits的長度,並將其複製給n,然後從角標n-1開始,逆向遍歷整個數組,由於i是從n-1開始,我們先判斷當前位置是否是9,如果是9,那麼就把把當前位置置0,並向前遍歷到前一個位置,只要前一個位置不是9,那麼就把此時的位置加1,然後返回。如果全體循環結束都沒有返回,那麼說明傳入的必然是999這種類型的。那麼出了循環之後,先把角標0改爲1,並再增加一個0,就完成了全部的計算過程。

課程鏈接:https://edu.csdn.net/course/detail/25037

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