LeetCode题解(Week 3):445. Add Two Numbers II

原题目

You are given two non-empty linked lists representing two non-negative
integers. The most significant digit comes first 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.

Follow up: What if you cannot modify the input lists? In other words,
reversing the lists is not allowed.

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

中文大意

给定两个非空链表,其中链表头部元素代表最高位,尾部代表最低位,计算出这两个链表作为两个十进制数相加的结果,如 (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) = (7 -> 8 -> 0 -> 7),另外,这道题能否通过不改变输入链表的结构(不将链表逆置)得到?

题解1:通过链表逆置实现

class Solution {
public:
    ListNode* reverseList(ListNode* head) 
    {
        if(head==NULL) return head;
        ListNode *tail = head;
        while(tail->next!=NULL)
            tail = tail->next;
        ListNode* curr = head;
        while(curr!=tail)
        {
            ListNode* currNext = curr->next;
            curr->next = tail->next;
            tail->next = curr;
            curr = currNext;
        }
        return tail;
    }

    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) 
    {
        ListNode* dummy = new ListNode(-1);  //创建结果的链表头部

        // 先将链表逆置
        ListNode* l1_reverse = reverseList(l1);
        ListNode* l2_reverse = reverseList(l2);

        int carry = 0; //处理进位
        while(l1_reverse!=NULL || l2_reverse!=NULL)
        {
            //处理两个链表不等长,遍历完其中的一个链表的情况
            if(l1_reverse==NULL)
            {
                ListNode* newNode = new ListNode((l2_reverse->val + carry)%10);
                carry = (l2_reverse->val + carry)/10;
                newNode->next = dummy->next;
                dummy->next = newNode;
                l2_reverse = l2_reverse->next;
            }
            else if(l2_reverse ==NULL)
            {
                ListNode* newNode = new ListNode((l1_reverse->val + carry)%10);
                carry = (l1_reverse->val + carry)/10;
                newNode->next = dummy->next;
                dummy->next = newNode;
                l1_reverse = l1_reverse->next;               
            }
            //常规情况
            else
            {
                ListNode* newNode = new ListNode((l1_reverse->val+ l2_reverse->val + carry)%10);
                carry = (l1_reverse->val+ l2_reverse->val + carry)/10;
                newNode->next = dummy->next;
                dummy->next = newNode;
                l1_reverse = l1_reverse->next;
                l2_reverse = l2_reverse->next;
            }
        }
        if(carry)  //如果最高位相加的结果还产生进位,这里需要加上
        {
            ListNode* newNode = new ListNode(carry);
            newNode->next = dummy->next;
            dummy->next = newNode;
        }
        return dummy->next;
    }
};

题解1分析

这道题实际上就是模拟两个数的竖式计算,关键是对链表的遍历以及对进位的处理,进位需要用一个额外的变量来存储,等于上一次进位加上当前位的两个加数除10取整。每一位相加的结果都要插入到新的链表的头部,从而避免最后还要对链表进行逆置


题解2:通过栈的实现

class Solution {
public:

    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        stack<int> s1,s2;
        //将两个链表中的数分别压到两个栈中
        while(l1!=NULL){
            s1.push(l1->val);
            l1 = l1->next;
        }
        while(l2!=NULL){
            s2.push(l2->val);
            l2 = l2->next;
        }
        ListNode *dummy = new ListNode(-1);
        int carry = 0;
        while(!s1.empty()||!s2.empty()){
            int sum = carry;
            if(!s1.empty()) {
                sum += s1.top();
                s1.pop();
            }
            if(!s2.empty())
            {
                sum += s2.top();
                s2.pop();
            }
            ListNode *newDigit = new ListNode(sum%10);
            carry = sum/10;
            //从头插入
            newDigit->next = dummy->next;
            dummy->next=newDigit;
        }
        if(carry)
        {
            ListNode *newDigit = new ListNode(carry);
            newDigit->next = dummy->next;
            dummy->next = newDigit;
        }
        return dummy->next;
    }
};

题解2分析

实际上这道题的解题思路是完全一样的,没有对链表本身进行逆置,只不过是对栈而不是链表进行操作,但空间复杂度比之前的要大(O(n)),同样需要注意两点:1. 进位的处理;2. 每次加法的结果插入到头部

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值