zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    模块
    Queue(队列)
    Stack(栈)
    Vector(容器)
    位图像素的颜色
    大数处理之三(除法)
    大数处理之二(幂运算)
    浮点数(double)的优势
    大数处理之一(加法和乘法)
    Depth-First Search
  • 原文地址:https://www.cnblogs.com/paulprayer/p/10079731.html
Copyright © 2011-2022 走看看