1. 程式人生 > >2. Add Two Numbers題目和答案詳解

2. Add Two Numbers題目和答案詳解

1 題目簡述

You are given two non-empty linked lists representing twonon-negative integers. The digits are stored in reverse order and each of their nodes contain asingle digit. Add the two numbers and return it as a linked list.

給出兩個表示兩個非負整數的非空連結串列。數字以相反的順序儲存,它們的每個節點都包含一個數字。相加兩個數字,並返回相加後的連結串列。

You may assume the twonumbers do not contain any leading zero, except the number 0 itself.

你可以假設這兩個數字不包含任何高位0,除了第0個數字本身。

Example

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)

Output: 7 -> 0 -> 8

Explanation: 342 + 465 = 807.

2 答案詳解

(1) 解決思想

首先,要知道兩個數相加有以下6種情況:

  1) 兩個數的位數相同,相加時不存在進位。例如:111+222=333。

  2) 兩個數的位數相同,相加時存在進位,但結果沒有增加位數。例如:105+205=310。

  3) 兩個數的位數相同,相加時存在進位,且結果增加了位數。例如:505+555=1060。

  4) 兩個數的位數不同,相加時不存在進位。例如:111+5=116。

  5) 兩個數的位數不同,相加時存在進位,但結果沒有增加位數。例如:105+5=110。

  6) 兩個數字的位數不同,相加時存在進位,且結果增加了位數。例如:999+1=1000。

  然後,初始化一個進位值carry為0,並遍歷兩個連結串列,針對所遇到的情況做如下處理:

  1)若此時遍歷到的兩個連結串列的結點均不為空,則將carry與當前遍歷到的兩個數字相加的結果對10取餘後,賦值給兩個連結串列當前的結點值;並將carry與當前遍歷到的兩個數字相加的結果/10後,更新給carry。

  2)若此時遍歷到的兩個連結串列的結點一個為空,一個不為空,則將carry與當前不為空結點的數字相加的結果對10取餘後,賦值給當前不為空的結點值;並將carry與當前不為空結點的數字相加的結果/10後,更新給carry。

  3)若此時遍歷到的兩個連結串列的結點均為空,但carry不為0,則作如下處理:

  a) 若兩個連結串列結點數相同,則任意選一個連結串列作為結果,並將另一個連結串列的頭結點值賦數字為carry,然後將該頭結點接在結果連結串列末尾。

  b) 若兩個連結串列結點數不同,則將結點數多的連結串列作為結果,並將結點數少的連結串列的頭結點數字賦值為carry,然後將該頭結點接在結果連結串列末尾。

  最後,返回結果連結串列。

(2) 設計程式

  所設計的程式採用類模板實現,程式如下:

#include <iostream>

using std::cout;
using std::endl;

struct ListNode {
    int val_;
    ListNode* next_;
    ListNode(int val):val_(val),next_(NULL) {}
};

template<class T>
class Solution
{
private:
    T& ListLeft_;
    T& ListRight_;
public:
    Solution(T& ListLeft, T& ListRight):ListLeft_(ListLeft),ListRight_(ListRight) {}
    T& AddTowNum();
};

template<class T>
T& Solution<T>::AddTowNum()
{
    int carry(0);
    int temp(0);
    T* posl = &ListLeft_;
    T* posr = &ListRight_;
    while(posl != NULL or posr != NULL or carry != 0 ) {
        if(posl != NULL and posr != NULL) {
            temp = (posl->val_ + posr->val_ + carry) / 10;
            posl->val_ =  posr->val_ = (posl->val_ + posr->val_ + carry) % 10;
            carry = temp;
            posl = posl->next_;
            posr = posr->next_;
        } else if(posl == NULL and posr != NULL) {
            temp = (posr->val_ + carry) / 10;
            posr->val_ = (posr->val_ + carry) % 10;
            carry = temp;
            posr = posr->next_;
        } else if(posr == NULL and posl != NULL) {
            temp = (posl->val_ + carry) / 10;
            posl->val_ = (posl->val_ + carry) % 10;
            carry = temp;
            posl = posl->next_;
            temp = -1;
        } else {
            if(temp == -1) {
                ListRight_.val_ = carry;
                ListRight_.next_ = NULL;
                posl = &ListLeft_;
                while(posl->next_ != NULL) {
                    posl = posl->next_;
                }
                (*posl).next_ = &ListRight_;
                posl = NULL;
            } else {
                ListLeft_.val_ = carry;
                ListLeft_.next_ = NULL;
                posr = &ListRight_;
                while(posr->next_ != NULL) {
                    posr = posr->next_;
                }
                (*posr).next_ = &ListLeft_;
                posr = NULL;
            }
            carry = 0;
        }

    }
    if(temp == -1) {
        return ListLeft_;
    } else {
        return ListRight_;
    }
}

void Show(ListNode& l)
{
    ListNode* pl = &l;
    while(pl != NULL) {
        cout << pl->val_;
        if(pl->next_ != NULL) {
            cout << "->";
        }
        pl = pl->next_;
    }
    cout << endl;
}


int main()
{
    cout << "142 + 9860 = " << int(142) + int(9860) << endl;
    ListNode nl1(2);
    ListNode nl2(4);
    ListNode nl3(1);
    nl1.next_ = &nl2;
    nl2.next_ = &nl3;
    ListNode nr1(0);
    ListNode nr2(6);
    ListNode nr3(8);
    ListNode nr4(9);
    nr1.next_ = &nr2;
    nr2.next_ = &nr3;
    nr3.next_ = &nr4;
    cout << "The left list:";
    Show(nl1);
    cout << "The right list:";
    Show(nr1);
    Solution<ListNode> sol(nl1,nr1);
    cout << "After add the two numbers:";
    Show(sol.AddTowNum());
}

程式執行結果為:

142 + 9860 = 10002
The left list:2->4->1
The right list:0->6->8->9
After add the two numbers:2->0->0->0->1