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