【算法問(wèn)題】如何實(shí)現(xiàn)大整數(shù)相加

如何實(shí)現(xiàn)大整數(shù)相加

摘自漫畫算法:

題目:給出兩個(gè)很大的整數(shù),要求實(shí)現(xiàn)程序求出兩個(gè)整數(shù)之和玄糟。

注意:很多人第一想法就是直接用long存儲(chǔ)勿她,在程序里相加不就行了;但是如果這兩個(gè)整數(shù)大得連long類型都裝不下呢阵翎?比如兩個(gè)100位的整數(shù)逢并?

解題思路

在講解大整數(shù)相加之前,先來(lái)回顧一下小學(xué)數(shù)學(xué)課郭卫,在上小學(xué)時(shí)砍聊,我們通過(guò)列豎式計(jì)算兩個(gè)較大數(shù)目的加、減贰军、乘玻蝌、除;那么词疼,為什么需要列出豎式來(lái)運(yùn)算呢俯树?這是因?yàn)閷?duì)于這么大的整數(shù),我們無(wú)法一步到位直接算出結(jié)果贰盗,所以不得不把計(jì)算過(guò)程拆解成一個(gè)一個(gè)子步驟许饿。其實(shí)不僅僅是人腦,對(duì)于計(jì)算機(jī)來(lái)說(shuō)也同樣如此舵盈。程序不可能通過(guò)一條指令計(jì)算出兩個(gè)大整數(shù)之和陋率,但我們卻可以把大運(yùn)算拆解成若干個(gè)小運(yùn)算球化,像小學(xué)生列豎式一樣按位計(jì)算。

如果大整數(shù)超出了long類型的范圍瓦糟,該如何來(lái)存儲(chǔ)這樣的整數(shù)呢支示?

對(duì)于這個(gè)問(wèn)題很好解決宾肺,用數(shù)組存儲(chǔ)即可。數(shù)組的每一個(gè)元素,對(duì)應(yīng)著大整數(shù)的每一個(gè)數(shù)位尖坤。

在程序中列出的”豎式“究竟是什么樣子呢持际?我們以426 709 752 318 + 95 481 253 129為例杰扫,來(lái)看看大整數(shù)相加的詳細(xì)步驟戴涝。

1、創(chuàng)建兩個(gè)整型數(shù)組斋竞,數(shù)組長(zhǎng)度是較大整數(shù)的位數(shù)+1.把每一個(gè)數(shù)組倒序存儲(chǔ)到數(shù)組中倔约,整數(shù)的個(gè)位存于數(shù)組下標(biāo)為0的位置,最高位存于數(shù)組的尾部坝初。之所以倒序存儲(chǔ)浸剩,是因?yàn)檫@樣更符合從左到右訪問(wèn)數(shù)組的習(xí)慣。

思路步驟 — 圖1.png

2鳄袍、創(chuàng)建結(jié)果數(shù)組绢要,結(jié)果數(shù)組的長(zhǎng)度同樣是較大整數(shù)的位數(shù)+1,+1的目的很明顯拗小,是給最高位進(jìn)位預(yù)留的重罪。

思路步驟 — 圖2.png

3、遍歷兩個(gè)數(shù)組哀九,從左到右按照對(duì)應(yīng)下標(biāo)把元素兩兩相加剿配,就像小學(xué)生計(jì)算豎式一樣。在本例中阅束,最先相加的是數(shù)組A的第1個(gè)元素8和數(shù)組B的第1個(gè)元素9呼胚,結(jié)果是7,進(jìn)位1息裸。把7填充到result數(shù)組的對(duì)應(yīng)下標(biāo)位置蝇更,進(jìn)位的1填充到下一個(gè)位置。

思路步驟 — 圖3.png

第2組相加的是數(shù)組A的第2個(gè)元素1和數(shù)組B的第2個(gè)元素2呼盆,結(jié)果3年扩,再加上剛才的進(jìn)位1,把4填充到result數(shù)組的對(duì)應(yīng)下標(biāo)位置宿亡。

思路步驟 — 圖4.png

第3組相加的是數(shù)組A的第3個(gè)元素3和數(shù)組B的第3個(gè)元素1常遂,結(jié)果是4,把4填充到result數(shù)組的對(duì)應(yīng)下標(biāo)位置挽荠。

思路步驟 — 圖5.png

第4組相加的是數(shù)組A的第4個(gè)元素2和數(shù)組B的第4個(gè)元素3克胳,結(jié)果是5,把5填充到result數(shù)組的對(duì)應(yīng)下標(biāo)位置圈匆。

思路步驟 — 圖6.png

以此類推漠另,一直把數(shù)組的所有元素都相加完畢。

4跃赚、把result數(shù)組的全部元素再次逆序笆搓,去掉首位0,就是最終結(jié)果纬傲。

思路步驟 — 圖7.png

需要說(shuō)明的是满败,為兩個(gè)大整數(shù)建立臨時(shí)數(shù)組,是一種直觀的解決方案叹括。若想節(jié)省內(nèi)存空間算墨,也可以不創(chuàng)建這兩個(gè)臨時(shí)數(shù)組。

代碼實(shí)現(xiàn)

/**
 * 描述:實(shí)現(xiàn)大整數(shù)相加汁雷。
 * <p>
 * Create By ZhangBiao
 * 2020/6/9
 */
public class BigNumberSum {

    /**
     * 大整數(shù)求和
     *
     * @param bigNumberA 大整數(shù)A
     * @param bigNumberB 大整數(shù)B
     * @return
     */
    public static String bigNumberSum(String bigNumberA, String bigNumberB) {
        // 1净嘀、把兩個(gè)大整數(shù)用數(shù)組逆序存儲(chǔ),數(shù)組長(zhǎng)度等于較大整數(shù)位數(shù)+1
        int maxLength = bigNumberA.length() > bigNumberB.length() ? bigNumberA.length() :
                bigNumberB.length();
        int[] arrayA = new int[maxLength + 1];
        for (int i = 0; i < bigNumberA.length(); i++) {
            arrayA[i] = bigNumberA.charAt(bigNumberA.length() - 1 - i) - '0';
        }
        int[] arrayB = new int[maxLength + 1];
        for (int i = 0; i < bigNumberB.length(); i++) {
            arrayB[i] = bigNumberB.charAt(bigNumberB.length() - 1 - i) - '0';
        }
        // 2侠讯、構(gòu)建result數(shù)組挖藏,數(shù)組長(zhǎng)度等于較大整數(shù)位+1
        int[] result = new int[maxLength + 1];
        // 3、遍歷數(shù)組厢漩,按位相加
        for (int i = 0; i < result.length; i++) {
            int temp = result[i];
            temp += arrayA[i];
            temp += arrayB[i];
            // 判斷是否進(jìn)位
            if (temp >= 10) {
                temp = temp - 10;
                result[i + 1] = 1;
            }
            result[i] = temp;
        }
        // 4膜眠、把result數(shù)組再次逆序并轉(zhuǎn)成String
        StringBuilder sb = new StringBuilder();
        // 是否找到大整數(shù)的最高有效位
        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"));
    }

}

上述代碼中,如果給出的大整數(shù)的最長(zhǎng)位數(shù)是n溜嗜,那么創(chuàng)建數(shù)組柴底。按位運(yùn)算、結(jié)果逆序的時(shí)間復(fù)雜度各自都是O(n)粱胜,整體的時(shí)間復(fù)雜度也是O(n)柄驻。不過(guò)當(dāng)前的思路其實(shí)還存在一個(gè)可優(yōu)化的地方。

優(yōu)化方案

我們之前是把大整數(shù)按照數(shù)位來(lái)拆分的焙压,即如果較大整數(shù)有50位鸿脓,那么我們就需要?jiǎng)?chuàng)建一個(gè)長(zhǎng)度為51的數(shù)組,數(shù)組中的每個(gè)元素存儲(chǔ)其中一位數(shù)字涯曲。

優(yōu)化 — 圖1.png

那么我們真的有必要把原整數(shù)拆分得這么細(xì)嗎野哭?顯然不需要,只需要拆分到可以被直接計(jì)算的程序就夠了幻件。

int類型的取值范圍是 -2 147 483 648 ~ 2 147 483 647拨黔,最多可以有10位整數(shù)。為了防止溢出绰沥,我們可以把大整數(shù)的每9位作為數(shù)組的一個(gè)元素篱蝇,進(jìn)行加法運(yùn)算贺待。(這里也可以使用long類型來(lái)拆分,按照int類型拆分僅僅是提供一個(gè)思路)零截。

優(yōu)化 — 圖2.png

如此一來(lái)麸塞,內(nèi)存占用空間和運(yùn)算次數(shù),都?jí)嚎s到了原來(lái)的1/9涧衙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哪工,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子弧哎,更是在濱河造成了極大的恐慌雁比,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撤嫩,死亡現(xiàn)場(chǎng)離奇詭異偎捎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)非洲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門鸭限,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人两踏,你說(shuō)我怎么就攤上這事败京。” “怎么了梦染?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵赡麦,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我帕识,道長(zhǎng)泛粹,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任肮疗,我火速辦了婚禮晶姊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伪货。我一直安慰自己们衙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布碱呼。 她就那樣靜靜地躺著蒙挑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪愚臀。 梳的紋絲不亂的頭發(fā)上忆蚀,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼馋袜。 笑死男旗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桃焕。 我是一名探鬼主播剑肯,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼捧毛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼观堂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起呀忧,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤师痕,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后而账,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體胰坟,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年泞辐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了笔横。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咐吼,死狀恐怖吹缔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锯茄,我是刑警寧澤厢塘,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站肌幽,受9級(jí)特大地震影響晚碾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喂急,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一格嘁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧廊移,春花似錦糕簿、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至步氏,卻和暖如春响禽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工芋类, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隆嗅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓侯繁,卻偏偏與公主長(zhǎng)得像胖喳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贮竟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345