LeetCode:Add Two Numbers

題目連接html

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.node

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 –> 8git

大整數加法算法


注意:鏈表中,整數的低位在前                       本文地址

/**
 * 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 carryBit = 0;
        ListNode tmpHead(0), *res = &tmpHead;
        while(l1 && l2)
        {
            l1->val += (l2->val + carryBit);
            carryBit = l1->val / 10;
            l1->val %= 10;
            res->next = l1;
            res = l1;
            
            l1 = l1->next;
            l2 = l2->next;
        }
        ListNode *p = (l1 == NULL ? l2 : l1); //此時l1,l2至多一個不爲NULL
        while(p)
        {
            if(carryBit == 0)
            {
                res->next = p;
                break;
            }
            else
            {
                p->val += carryBit;
                carryBit = p->val / 10;
                p->val %= 10;
                res->next = p;
                res = p;
            }
            p = p->next;
        }
        if(carryBit != 0)res->next = new ListNode(carryBit);
        
        return tmpHead.next;
    }
};


若是鏈表存儲整數時,高位在前,該如何處理。測試

一、最簡單的想法是,能夠先把鏈表反轉,而後調用上面的算法,最後把結果反轉。3d

二、可不能夠從高位向低位方向處理呢?咱們知道進位是從低位傳向高位的,若是從高位向低位方向計算,當計算到某一位須要進位時,有沒有辦法知道該進位傳遞到前面的哪一位呢?從如下幾個例子來看:code

image

從最高位到最低位咱們依次記爲第 1,2…,7位。圖中紅色標記的位置是:下一次須要進位時,進位的1放置的位子htm

第1位相加,結果爲12,須要進位,這個進位放到第0位;同時標記第1位爲下一次的進位標誌blog

第2位相加,結果爲3,不須要進位;標記第2位爲下一次進位標誌ip

第3位相加,結果爲3,不須要進位;標記第3位爲下一次進位標誌

第4位相加,結果爲9,不須要進位;此時進位標誌不須要移動,由於9加上一個進位後還要繼續向前進位

第5位相加,結果爲9,不須要進位;此時進位標誌不須要移動,由於9加上一個進位後還要繼續向前進位

第6位相加,結果爲14,須要進位,這個進位放到前面標記的第3位上,同時把第4位和第5位置0,標記第6位爲下一次進位標誌

第7位同上

 

因此綜上所述,從高位往低位計算加法時,規則是:

1、若是當前位沒有進位:(1)若是當前位的和小於9,則把改位設置成下一次進位標誌(2)若是和等於9,進位標誌不變

2、若是當前位有進位:把進位的1加到前面標誌的位子上,同時把標誌位和當前位之間的位所有置0(由於他們之間的位確定所有都是9),把當前位設置成進位標誌

 

上面咱們舉例的兩個加數長度一致,若是長度不相同,則要先處理較長的整數的前面多出的部分。

 

咱們把這一題leetcode的輸入反轉,測試代碼以下:

/**
 * 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) {
        l1 = reverseList(l1);
        l2 = reverseList(l2);
        int n1 = lenList(l1), n2 = lenList(l2);
        if(n1 < n2)//l1 指向較長的鏈表
        {
            swap(n1,n2);
            swap(l1,l2);
        }
        //carryLoc是下一次出現進位時,進位的1將要放置的位子,pre指向當前結果鏈表的最後一個節點
        //p1,p2分別是當前處理的l1,l2節點
        //因爲加數的最高位有可能進位,因此添加一個新的節點newHead
        ListNode *newHead = new ListNode(0), *carryLoc = newHead, *pre = newHead, *p1 = l1;
        for(int i = 0; i < n1-n2; i++)//處理l1高位長出的部分
        {
            if(p1->val < 9)carryLoc = p1;
            pre->next = p1;
            pre = p1;
            p1 = p1->next;
        }
        ListNode* p2 = l2;
        while(p1 != NULL)
        {
            pre->next = p1;
            pre = p1;
            
            p1->val += p2->val;
            if(p1->val > 9)
            {
                carryLoc->val += 1;
                for(carryLoc = carryLoc->next; carryLoc != p1; carryLoc = carryLoc->next)//carryLoc到p1之間的節點所有置0
                    carryLoc->val = 0;
                p1->val -= 10;
            }
            if(p1->val < 9)
                carryLoc = p1;
            
            p1 = p1->next;
            p2 = p2->next;
        }
        if(newHead->val != 0)return reverseList(newHead);
        else return reverseList(newHead->next);
    }
    //反轉鏈表
    ListNode *reverseList(ListNode *l1)
    {
        ListNode *p = l1->next, *pre = l1;
        l1->next = NULL;
        while(p)
        {
            ListNode *tmp = p->next;
            p->next = pre;
            pre = p;
            p = tmp;
        }
        return pre;
    }
    //求鏈表長度
    int lenList(ListNode *head)
    {
        int res = 0;
        while(head)
        {
            res++;
            head = head->next;
        }
        return res;
    }
};

 

 

 

【版權聲明】轉載請註明出處:http://www.cnblogs.com/TenosDoIt/p/3735362.html

相關文章
相關標籤/搜索