1. 程式人生 > >LeetCode修仙:Add Two Numbers

LeetCode修仙:Add Two Numbers

problem:

You are given two non-empty linked lists representing two non-negative integers. 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.

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

Example

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

方法1:

思路:

首先我會習慣性暴力解決一下:其實就是兩個數相加,很簡單,但是給你的結構式連結串列:所以就是連結串列和數字之間的轉換。


我們看到:第一個框框就是連結串列,已知;然後中間的框框就是轉化為數字,簡單相加;然後第三個框框的return;難點(如果有)就在框框之間的轉換。

程式碼展示:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        int num1=0,num2=0,i=0,j=0,ans=0;
        
        if (l1 == NULL) return l2; 
		else if (l2 == NULL) return l1; 
        
        while(l1 != NULL)
        {
            num1 = num1+(10^i)*l1->val;
            i++;
            l1=l1->next;
        }
        while(l2 != NULL)
        {
            num2 = num2+(10^j)*l2->val;
            j++;
            l2=l2->next;
        }
        ans = num1+num2;
        
        ListNode *answer = new ListNode(ans % 10);
        answer->next = NULL;
        ListNode *l3 = answer;
        ans = ans/10;
        answer = answer->next;
        while(ans!=0);
        {
            answer->val = ans%10;
            ans = ans/10;
            answer = answer->next;
        }
        return l3;
    }
};
分析:一進來定義i、j記錄兩個連結串列長度;num1、num2記錄兩個連結串列所記錄的數字;ans記錄相加數字的結果;answer記錄第三個連結串列,l3記錄返回的第三個連結串列的頭部;

執行結果:


哈哈哈,時間限制超出範圍了;也就是執行時間太長了:這就是暴力解決問題的碰壁~~~

方法2、

思路:

可以看到,這個演算法其實很沒有必要,沒有必要去轉化為數字,只需要兩個連結串列逐個相加>>會遇到什麼問題>>如果兩者加需要進位怎麼辦>>那就多增加一個記錄加減進位的值就好了>>問題解決。

程式碼:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
       if (l1 == NULL) return l2; 
	   else if (l2 == NULL) return l1; 
       
       int carry=0;
       int ans = l1->val+l2->val;
       ListNode* answer = new ListNode(ans%10);
       ListNode* l3 = answer;
       answer->next = NULL;
       l1 = l1->next;
       l2 = l2->next;
       if(ans>=10) carry=1;
       while(l1 || l2 || carry)
       {
           ans = (l1? l1->val:0)+(l2? l2->val:0)+carry;
           answer->next = new ListNode(ans%10);
           answer = answer->next;
           carry = (ans >=10)? 1:0;
           l1 = l1? l1->next:l1;
           l2 = l2? l2->next:l2;
           
       }
       return l3;
    }
};

分析:

方法2中、程式碼前部分while之前,都是在定義第一個節點,while中只需要迴圈一次,並且考慮了兩條連結串列不一樣長的情況和最後一位需要進位的情況:而上面方法1,需要迴圈三次(三條連結串列);所以時間上放慢了三倍;

執行結果:


容易錯誤:

ans = l1->val+l2->val+carry;
代替:
ans = (l1? l1->val:0)+(l2? l2->val:0)+carry;
就會出現,當l2或者l1某個節點為NULL,而carry為1的時候,出現NULL+int+int的情況,這是不允許的;