咱們平時實現兩個整數相加,直接用兩個int類型的整數相加便可。若是整數再大一點,那麼就能夠將整數聲明爲long類型。若是整數是數十位的,甚至是上百位的,連long類型也裝不下呢?讓咱們來先回顧一下咱們上小學時是如何計算兩個較大的整數想加的。小學時,要計算兩個較大整數相加,就要進行列豎式計算,將兩個整數先右對齊,再從個位開始,到十位,到百位......依次進行加法運算。那麼咱們爲何要列出豎式運算呢?由於咱們人腦沒法將兩個很大的數一步到位直接計算出結果,必須拆解成一位一位的運算。一樣,程序不可能經過一條指令就計算出兩個大整數的和,也必須一位一位的運算。可是大整數既然超過了long類型的範圍,那麼計算機如何來存儲大整數呢?因而數組就派上用場了。咱們能夠用數組來存儲大整數的每一位。java
我以426709752318 + 95481253129爲例,來看看計算機進行兩個大整數相加的具體操做步驟:算法
第一步:因爲咱們都習慣從左往右地訪問數組,所以把整數倒序存儲,整數的個位存於數組0下標位置,最高位存於數組長度減1下標位置處。
數組
第二步:建立結果數組,該數組的長度應爲較大整數的位數加1。
app
第三步:遍歷兩個整數的數組,左對齊從左到右按照對應下標將元素相加。工具
例子中,首先相加的是數組A的第一個元素8和數組B的第一個元素9,得出結果7,進位1。把7填充到Result數組的對應下標,進位的1填充至下一位置:
優化
第二組相加的是數組A的第二個元素1和數組B的第二個元素2,得出結果3,再加上剛纔的進位1,結果是4,將4填充至Result數組的對應下標處:
ui
第三組相加的是數組A的第三個元素3和數組B的第三個元素1,得出結果4,將4填充至Result數組的對應下標處:
code
第四組相加的是數組A的第四個元素2和數組B的第四個元素3,得出結果5,將5填充至Result數組的對應下標處:
blog
以此類推......一直把兩個數組的全部元素都相加完畢:
ci
第四步:把Result數組的所有元素再次逆序,去掉首位,便可獲得最終結果:
代碼以下:
/** * 大整數求和 * @param bigNumberA 大整數A * @param bigNumberB 大整數B */ public static String bigNumberSum(String bigNumberA, String bigNumberB) { // 1.把兩個大整數用數組逆序存儲,數組長度等於較大整數位數+1 int maxLength = bigNumberA.length() > bigNumberB.length() ? bigNumberA.length() : bigNumberB.length(); int[] arrayA = new int[maxLength + 1]; int[] arrayB = new int[maxLength + 1]; for(int i = 0; i < bigNumberA.length(); i++) arrayA[i] = bigNumberA.charAt(bigNumberA.length() - 1 - i) - '0'; for(int i = 0; i < bigNumberB.length(); i++) arrayB[i] = bigNumberB.charAt(bigNumberB.length() - 1 - i) - '0'; // 2.構建result數組,數組長度等於較大整數位數 + 1 int[] result = new int[maxLength + 1]; // 3.遍歷數組,按位相加 for(int i = 0; i < result.length; i++) { int temp = result[i]; temp += arrayA[i] + arrayB[i]; // 判斷是否進位 if(temp >= 10) { temp = temp - 10; result[i + 1] = 1; } result[i] = temp; } // 4.把result數組再次逆序並轉成String StringBuilder sb = new StringBuilder(); //是否找到大整數的最高有效位 boolean findFirst = false; for(int i = result.length - 1; i >= 0; i--) { if(!findFirst) { if(result[i] == 0) continue; findFirst = true; } sb.append(result[i]); } return sb.toString(); } public static void main(String[] args) { System.out.println(bigNumberSum("426709752318", "95481253129")); }
咱們來分析下這個算法的時間複雜度,若是給定的大整數的最長位數是n,那麼建立數組、按位計算、結果逆序的時間複雜度均是O(n),所以總體時間複雜度是O(n)。
這個還有一個優化的地方。咱們以前是把大整數按照每個十進制數位來拆分,好比較大整數位的長度有50位,那麼咱們須要建立一個51位的數組,數組的每一個元素均存儲一位。
咱們真的有必要把整數拆得那麼細嗎?很顯然不必。只須要拆分到能夠被直接計算的程度便可。
咱們都知道int類型的取值範圍是-2147483648~2147483647,最多有10位整數。爲了防止溢出,咱們能夠把大整數的每9位做爲數組的一個元素進行加法運算。
如此一來,佔用空間和運算次數都被壓縮了9倍。其實,在Java中,工具類BigInteger和BigDecimal的底層實現也是把大整數拆分紅數組進行運算,與此方法大致相同。