2. 两数相加

问题链接

https://leetcode.cn/problems/add-two-numbers/description/

解题思路

这题是倒着存储的,也要求我们返回一个倒着的链表。 即它需要我们左对齐,相加之后向后进位,但需要我们返回最左侧的结果节点。

看起来这也是个缩小规模的问题。

首先,我们考虑参数和返回值。

我们自己定义一个handler函数当做递归函数,l1, l2分别为2个链表。 l为处理好的链表的最后一个非空结点(待会儿可以看到有啥用)。p_num为本层处理的进位。

我们之所以需要l,是因为我们如果碰到两个数字最后向外进一个1的情况,我们需要新建一个结点来存储这个1,我们要把1连接在结果链表上,所以需要l来指向处理好的结果链表的最后一个有效节点。

由于这个题目要求我们返回处理链表的头结点,所以我们直接原地修改即可,handler函数本身不需要返回什么。

然后我们来考虑正常情况下本层应该做什么。(我们定义的正常情况指的是需要进行递归退出的情况)

首先,我们来考虑两个结点都有值的情况(不为None)

我们需要把l1.val 和 l2.val和p_num(上一层的进位)都加起来,计算一个原始的结果ori_num

这个原始的结果,%10就是本层的结果。

我们省点事儿,直接原地修改,存储在l1中。

然后将l指向l1(即指向处理好的链表的最后一个结点)

然后我们计算向下一层的进位 nxt_num = ori_num // 10。

然后就可以进入到下一层的递归处理了。

然后我们考虑稍微异常点的情况(但不至于直接终止递归)

l1或者l2没值,怎么办?

首先进行归一化的处理,我们刚刚认定把数值存储在l1中,所以如果l1没值,那么我们就交换l1和l2, 强行让l1变得有值。

但这样的话,l1此时代表的就不是处理好的结果链表的最后一个结点了,因为我们选定l1为结果链表,但此时l1代表的实际上是l2这条链表。

所以我们需要利用处理好的链表的最后一个结点指向此时的l1, 即将结果链表和备胎链表连接起来。

然后走上面考虑的流程即可。

最后,我们考虑退出条件。 当l1和l2都为空时,我们需要考虑此时进位的数值。如果有进位,则需要弄一个新节点存储,并且将其接在l上。

如果没进位,那直接结束运行即可。

代码

# Definition for singly-linked list.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def addTwoNumbers(self, l1, l2):
        self.handler(l1, l2, l1, 0)
        return l1
    def handler(self, l1, l2, l, p_num):
        if l1 is None and l2 is None:
            if p_num != 0:
                ll = ListNode(p_num)
                l.next = ll
            return
        if l1 is None:
            l1, l2 = l2, l1
            l.next = l1
        ori_num = l1.val + (0 if l2 is None else l2.val) + p_num
        l1.val = ori_num % 10
        nxt_num = ori_num // 10
        self.handler(l1.next, l2 if l2 is None else l2.next, l1, nxt_num)

 优雅实现:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        return self.dfs(l1, l2, 0)
    
    def dfs(self, l1, l2, last):
        if not l1 and not l2 and last != 0:
            node = ListNode(val=last)
            return node
        if l1 and l2:
            val, nxt = (l1.val + l2.val + last) % 10, (l1.val + l2.val + last) // 10
            l1.val = val
            l1.next = self.dfs(l1.next, l2.next, nxt)
            return l1
        if l1:
            val, nxt = (l1.val + last) % 10, (l1.val + last) // 10
            l1.val = val
            l1.next = self.dfs(l1.next, l2, nxt)
            return l1
        if l2:
            val, nxt = (l2.val + last) % 10, (l2.val + last) // 10
            l2.val = val
            l2.next = self.dfs(l1, l2.next, nxt)
            return l2

 

posted @ 2023-01-05 22:53  BJFU-VTH  阅读(33)  评论(0编辑  收藏  举报