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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值