【LeetCode】兩數相加


題目描述

給出兩個非空的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照逆序的方式存儲的,並且它們的每個節點只能存儲一位數字。

如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。

您可以假設除了數字0之外,這兩個數都不會以0開頭。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

題目解析

這個題目的意思看起來其實很簡單,提供了兩個鏈表,每個鏈表代表一個非負整數,它們各自的位數是按照逆序方式存儲的,例如:(2 -> 4 -> 3)代表整數342(5 -> 6 -> 4)則代表整數465,兩數相加的結果自然是807,這就是我們要給出的答案,但是要用鏈表的形式返回7 -> 0 -> 8。題目中說明了是非空鏈表,所以就不用考慮鏈表為null的情況了。

乍眼一看,很簡單啊,不就是把兩個數相加嘛,我先把它整成整數,然后相加,最后把結果整成鏈表,完美,哈哈哈哈,簡直被自己的聰明才智給折服。

翻車嘗試1:蝦扯蛋法

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head1 = l1;
        ListNode head2 = l2;
        int i = 0;
        int j = 0;
        int index = 0;
        // 將鏈表l1轉化為整數
        while (head1 != null) {
            i += head1.val * Math.pow(10, index);
            index++;
            head1 = head1.next;
        }
        index = 0;
        // 將鏈表l2轉化為整數
        while (head2 != null) {
            j += head2.val * Math.pow(10, index);
            index++;
            head2 = head2.next;
        }
        int sum = i + j;
        ListNode newHead = new ListNode(0);
        ListNode tmpHead = newHead;
        int sign = 0;
        // 將結果轉化為鏈表
        while (sum > 0 || sign == 0) {
            int tmp = sum % 10;
            sum = sum / 10;
            tmpHead.next = new ListNode(tmp);
            tmpHead = tmpHead.next;
            sign++;
        }
        return newHead.next;
    }
}

簡直輕松加愉快,讓我們來提交一下。

怎么肥四,小老弟,翻車了啊。讓我們看看錯誤原因:

輸入:
[9]
[1,9,9,9,9,9,9,9,9,9]
輸出:
[0]
預期:
[0,0,0,0,0,0,0,0,0,0,1]

看樣子應該是整數型溢出了。。。難不倒我,改成long型不就完事了。

翻車嘗試2:蝦扯蛋升級法

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head1 = l1;
        ListNode head2 = l2;
        long i = 0;
        long j = 0;
        long index = 0;
        while (head1 != null) {
            i += head1.val * Math.pow(10, index);
            index++;
            head1 = head1.next;
        }
        index = 0;
        while (head2 != null) {
            j += head2.val * Math.pow(10, index);
            index++;
            head2 = head2.next;
        }
        long sum = i + j;
        ListNode newHead = new ListNode(0);
        ListNode tmpHead = newHead;
        int sign = 0;
        while (sum > 0 || sign == 0) {
            int tmp = (int)(sum % 10);
            sum = sum / 10;
            tmpHead.next = new ListNode(tmp);
            tmpHead = tmpHead.next;
            sign++;
        }
        return newHead.next;
    }
}

這次總沒事了吧,再提交一下:

這個磨人的小妖精,整出個這么大的數來折騰我,long型也溢出了。。。

逼我用絕招,是時候祭出我的BigInteger了。

翻車嘗試3:蝦扯蛋終極法

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head1 = l1;
        ListNode head2 = l2;
        BigInteger i = new BigInteger(0);
        BigInteger j = new BigInteger(0);
        long index = 0;
        while (head1 != null) {
            i.add(BigInteger.valueOf(head1.val * Math.pow(10, index)));
            index++;
            head1 = head1.next;
        }
        index = 0;
        while (head2 != null) {
            j.add(BigInteger.valueOf(head2.val * Math.pow(10, index)));
            index++;
            head2 = head2.next;
        }
        BigInteger sum = i.add(j);
        ListNode newHead = new ListNode(0);
        ListNode tmpHead = newHead;
        int sign = 0;
        while (sum.compareTo(0) == 1 || sign == 0) {
            int tmp = sum.mod(10).intValue();
            sum = sum.divide(10);
            tmpHead.next = new ListNode(tmp);
            tmpHead = tmpHead.next;
            sign++;
        }
        return newHead.next;
    }
}

這次,連編譯都不通過了,emmmm,看來不准用BigInteger這個類。

常規解法

既然邪門歪道走不通,那就還是用常規操作來解決吧,仔細想想,其實也很簡單,我們從兩個鏈表的頭節點開始,一起遍歷,將相加得到的結果存入新的鏈表中即可。

這里需要注意的就是要考慮進位的情況,比如:4 + 6 = 10,那么在處理后一個節點3 + 4的時候,需要再加1,因此需要有一個進位標志來表示是否需要進位。

另外,兩個鏈表的長度並不一定相等,需要考慮像上面那樣一個很長,一個很短,而且后續一直進位的情況:

[9]
[1,9,9,9,9,9,9,9,9,9]

所以我們可以定義一個叫carry的變量來表示是否需要進位。

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head1 = l1;
        ListNode head2 = l2;
        ListNode newHead = new ListNode(0);
        ListNode head3 = newHead;
        // 進位標志
        boolean carry = false;
        while (head1 != null || head2 != null) {
            // 獲取對應位置的值然后相加
            int x = (head1 != null) ? head1.val : 0;
            int y = (head2 != null) ? head2.val : 0;
            int sum = carry ? (x + y + 1) : (x + y);
            // 處理進位
            if (sum >= 10){
                sum -= 10;
                carry = true;
            } else {
                carry = false;
            }
            // 新增節點
            head3.next = new ListNode(sum % 10);
            head3 = head3.next;
            if (head1 != null) head1 = head1.next;
            if (head2 != null) head2 = head2.next;
        }
        if (carry) {
            head3.next = new ListNode(1);
        }
        return newHead.next;
    }
}

嗯,這下就沒什么問題了。😜

本題中文版鏈接

本題英文版鏈接

如果你有更好的解法,歡迎留言討論~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM