2. 两数相加

679 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

题目描述

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

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

image.png

截屏2022-04-24 上午10.24.24.png

思路分析

由于加法运算需要从右到左,这和链表本身想悖,如果从左到右计算的话,需要较为复杂的逻辑处理进位,因此我们可以设置一个栈,不断地将链表分别写入两个栈中,利用栈的后进先出的性质,从而达到从右到左计算的目的。

啊不过这就是典型的没看题目,事实上链表本身是逆序给出,因此不再需要栈来对数据进行处理,那就需要用循环去逐个遍历。

遍历条件可以是两个链表任一不为空(否则要写两次while,比较麻烦)。

每次遍历计算当前两个节点值相加,以及判断上一位是否有进位,并计算这一位是否进位。

最后遍历结束时再判断一次进位即可。

具体实现

 ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *head = nullptr, *tail = nullptr;
        int carry = 0;
        while (l1 || l2) {
            int n1 = l1 ? l1->val: 0;
            int n2 = l2 ? l2->val: 0;
            int sum = n1 + n2 + carry;
            if (!head) {
                head = tail = new ListNode(sum % 10);
            } else {
                tail->next = new ListNode(sum % 10);
                tail = tail->next;
            }
            carry = sum / 10;
            if (l1) {
                l1 = l1->next;
            }
            if (l2) {
                l2 = l2->next;
            }
        }
        if (carry > 0) {
            tail->next = new ListNode(carry);
        }
        return head;
    }

总结

这道题本身难度不大,并没有使用什么数据结构和算法,时间复杂度也是O(N)。