题目难度: 中等

原题链接

今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给定两个用链表表示的整数,每个节点包含一个数位。

这些数位是反向存放的,也就是个位排在链表首部。

编写函数对这两个整数求和,并用链表形式返回结果。

示例:

  • 输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即 617 + 295
  • 输出:2 -> 1 -> 9,即 912

题目思考

  1. 假设这些数位是正向存放的,又该如何解决呢?

示例:

  • 输入:(6 -> 1 -> 7) + (2 -> 9 -> 5),即 617 + 295
  • 输出:9 -> 1 -> 2,即 912

解决方案

思路

  • 因为数位是反向存放的, 所以可以直接利用逐位相加: 将每一位进行求和, 如果大于 10 的话进位为 1, 放在下一位继续求和即可
  • 特别注意最高位进位为 1 的特殊情况, 比如 99+1. 所以可以将进位是否为 0 也作为循环的条件, 统一起来, 从而避免遗漏, 具体参见下面的代码部分
  • 接下来考虑进阶问题: 节点正向存放时怎么解决?
  • 很容易想到的思路就是将输入链表进行翻转, 求完和之后再翻转一次, 从而使得最终的和也满足正向存放. 对应下面代码中的 addTwoNumbersInForwardDirection 方法

复杂度

  • 时间复杂度 O(M+N): 只需要遍历每个节点一遍
  • 空间复杂度 O(max(M,N)): 需要新建一个链表, 其节点数目为 M 或 N 的较大值(也可能多 1, 对应的是最高位进位为 1 的情况). 如果允许修改输入节点的话, 则可以直接在某个链表基础上改值, 从而将空间复杂度降为 O(1)

代码

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        # 使用哨兵节点, 作为新的链表头的前一位
        dummy = ListNode(0)
        cur = dummy
        # carry存储当前进位
        carry = 0
        # 将carry是否为0也作为循环条件, 如果两个链表都遍历完毕但仍有进位时, 也需要进行处理
        while l1 or l2 or carry:
            if l1:
                carry += l1.val
                l1 = l1.next
            if l2:
                carry += l2.val
                l2 = l2.next
            # 求当前位的和, 以及新的进位
            carry, sm = divmod(carry, 10)
            cur.next = ListNode(sm)
            cur = cur.next

        return dummy.next

    def addTwoNumbersInForwardDirection(self, l1: ListNode,
                                        l2: ListNode) -> ListNode:
        # 正向存放的话
        # 先转成反向, 然后调用addTwoNumbers, 最后再把结果反过来
        def reverse(root):
            if not root:
                return root
            # 经典三指针链表翻转
            pre = None
            cur = root
            while cur:
                nex = cur.next
                cur.next = pre
                pre = cur
                cur = nex
            return pre

        return reverse(self.addTwoNumbers(reverse(l1), reverse(l2)))

大家可以在下面这些地方找到我~😊

我的知乎专栏

我的头条号

我的 CSDN

我的 Leetcode

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我