Add Two Numbers(基於連結串列的兩數相加)
阿新 • • 發佈:2019-01-08
You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.(給定兩個代表非負數的連結串列,所有數字都以逆序排列而且每個節點只包含一個數字,將這兩個數相加並且以連結串列的形式返回)
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
1.個人分析
由題意和示例可以看出,連結串列從第一個節點開始,依次表示非負數的個位、百位、千位等等。對連結串列每個節點進行相加操作也遵循正常的進位。最直接的做法是同時遍歷兩個連結串列,將每個節點進行相加,如果有進位,則對求和結果取餘,並在下一節點求和時加1。
2.個人解法
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
ListNode *res = new ListNode(0);//建立一個空節點作為結果連結串列的頭節點
ListNode *resCur = res;
ListNode *cur1 = l1;
ListNode * cur2 = l2;
int carry = 0; //進位值
//處理兩連結串列相同長度的情況
while (cur1 && cur2){
int tmp = cur1->val + cur2->val + carry;
carry = tmp >= 10 ?1 : 0;
int unit = tmp % 10;
ListNode *newNode = new ListNode(unit);
resCur->next = newNode;
resCur = newNode;
cur1 = cur1->next;
cur2 = cur2->next;
}
if(cur1){ //處理l1長度比l2長度更長的情況
while(cur1){
int tmp = cur1->val + carry;
carry = tmp >= 10 ?1 : 0;
cur1->val = tmp % 10;
resCur->next = cur1;
resCur = cur1;
cur1 = cur1->next;
}
}
else if(cur2){ //處理l2長度比l1長度更長的情況
while(cur2){
int tmp = cur2->val + carry;
carry = tmp >= 10 ?1 : 0;
cur2->val = tmp % 10;
resCur->next = cur2;
resCur = cur2;
cur2 = cur2->next;
}
}
//處理最高位進位情形
if(carry == 1){
ListNode *newNode = new ListNode(carry);
resCur->next = newNode;
resCur = newNode;
}
return res->next;
}
該解法的時間複雜度為O(n),空間複雜度為O(n),但整體流程顯得比較冗長。
3.參考解法
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
ListNode preHead(0), *p = &preHead;
int extra = 0;
while (l1 || l2 || extra) {
if (l1) extra += l1->val, l1 = l1->next;
if (l2) extra += l2->val, l2 = l2->next;
p->next = new ListNode(extra % 10);
extra /= 10;
p = p->next;
}
return preHead.next;
}
該解法的時間複雜度為O(n),空間複雜度為O(n),執行效率與第一種解法差不多,但整體程式碼更加精簡。
4.總結
該問題雖然不難想出解法,但需要考慮很多的細節,比如不等長的情形處理,最高位進位的處理,所以想要一次就AC不太容易。
PS:
- 題目的中文翻譯是本人所作,如有偏差敬請指正。
- 其中的“個人分析”和“個人解法”均是本人最初的想法和做法,不一定是對的,只是作為一個對照和記錄。