Leetcode 445. 两数相加 II

1.题目描述

给定两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

进阶:

如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。

示例:

输入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出: 7 -> 8 -> 0 -> 7

  

2.解法一:反转链表

2.1 思路

(1)将两个链表反转,就变成了Leetcode上的第二道题目“2.两数相加”;

(2)然后就是一样的思路:题中链表顺序正好是低位到高位,先低位相加,有进位保持,下一位计算加上进位,直到最高位相加,如果有进位,生成新的结点保存。

2.2 代码

class Solution {
public:
     
     //反转链表
     ListNode* reverseList(ListNode* l3) {
        if (!l3) return NULL;

        ListNode* r = new ListNode(l3->val);
        ListNode* h = r;
        ListNode* cur = l3->next;
        while (cur) {
            ListNode* temp = new ListNode(cur->val);
            temp->next = h;
            h = temp;
            cur = cur->next;
        }
        return h;
    }

    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        
        //逆序
        l1 = Solution::reverseList(l1);
        l2 = Solution::reverseList(l2);

        unsigned int carry = 0; //进位

        ListNode* Hl3 = new ListNode(0);
        ListNode* l3 = Hl3;

        int a = 0;
        int b = 0;
        int temp = 0;

        while (l1 != NULL || l2 != NULL)
        {
            //判断a和b的取值
            if (l1 == NULL) a = 0;
            else a = l1->val;
            if (l2 == NULL) b = 0;
            else b = l2->val;

            temp = (a + b + carry) % 10;

            //有无进位
            if ((a + b + carry) / 10 != 0)
                carry = 1;
            else
                carry = 0;

            //创建新结点,保存temp
            l3->next = new ListNode(temp);
            l3 = l3->next;

            if (l1) l1 = l1->next;
            if (l2) l2 = l2->next;
        }

        //最后的进位
        if (carry == 1) {
            l3->next = new ListNode(1);
        }
        
        //还原链表
        Hl3->next = Solution::reverseList(Hl3->next);
        return Hl3->next;
    }
};

3.解法二:不允许反转(进阶)

3.1 思路

关键还是在于逆序结构适应于这种情况。不需要考虑空间复杂性的话,为了方便,使用三个栈

    • 前两个栈s1和s2逆序保存两个链表l1和l2的结点值;
    • 第三个栈s3来保存前两个栈相加的结果,还原链表顺序;

3.2 代码

#include <iostream>
#include <stack>

using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        stack<int> s1;
        stack<int> s2;
        stack<int> s3;

        ListNode* Hl3 = new ListNode(0);
        ListNode* l3 = Hl3;

        //遍历两个链表入栈,进行逆序
        while (l1 != NULL) {
            s1.push(l1->val);
            l1 = l1->next;
        }
        while (l2 != NULL) {
            s2.push(l2->val);
            l2 = l2->next;
        }

        //用栈来相加
        int a = 0;
        int b = 0;
        int temp = 0;
        int carry = 0;

        while (!s1.empty() || !s2.empty()) {
            a = s1.size() == 0 ? 0 : s1.top();
            b = s2.size() == 0 ? 0 : s2.top();
            temp = a + b + carry;

            //有无进位
            carry = temp / 10 == 0 ? 0 : 1;

            s3.push(temp % 10);
            
            /*---常见错误总结---*/
            //不空,才能出栈
            if(!s1.empty()) s1.pop();
            if(!s2.empty()) s2.pop();
        }
        if (carry == 1)
            s3.push(1);


        //恢复顺序
        while (!s3.empty()) {
            l3->next = new ListNode(s3.top());
            l3 = l3->next;
            s3.pop();
        }
        return Hl3->next;
    }
};

int main()
{
    ListNode* p1 = new ListNode(7);
    ListNode* p2 = new ListNode(2);
    ListNode* p3 = new ListNode(4);
    ListNode* p4 = new ListNode(3);
    p1->next = p2;
    p2->next = p3;
    p3->next = p4;
    p4->next = NULL;

    ListNode* q1 = new ListNode(5);
    ListNode* q2 = new ListNode(6);
    ListNode* q3 = new ListNode(4);
    q1->next = q2;
    q2->next = q3;
    q3->next = NULL;

    Solution test;
    ListNode* t1 = test.addTwoNumbers(p1, q1);
    while (t1) {
        cout << t1->val << endl;
        t1 = t1->next;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/paulprayer/p/10079731.html