题目: 两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
1 | 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) |
思路
这题涉及数据结构和链表,这在Python中比较少,参考了官方解题思路才大概明白。
首先需要理解ListNode
这个class
。
1 | # Definition for singly-linked list. |
每个ListNode()
都有两个属性,一个是本身的值(val),另一个则是指向另一个ListNode()
对象。比如示例中的输出:7 -> 0 -> 8
。其实是三个ListNode()
对象,产生的过程如下:
1 | tmp = ListNode(0) |
对ListNode
这样的链表有了理解之后,解题就比较方便了:
- 先初始化一个tmp = ListNode(0) 的临时变量,并将res.next指向tmp,并初始化一个进位临时变量carry=0
- 遍历l1,l2直到都为None:
- 如果l1为None,则x值为0,否则x值为l1.val
- 如果l2为None,则y值为0,否则y值为l2.val
- x,y相加并加上上一轮相加的进位carry得到tmpSum,该轮tmp的值为和的tmpSum的个位(tmpSum%10),carry更新为tmpSum的十位(tmpSum//10)
- 将tmp在指向自己的下一个tmp.next
- 遍历结束后检查是否还有进位carry,有的话则tmp的下一位为ListNode(1)
- 返回结果:res.next
完整代码如下:
1 | # Definition for singly-linked list. |
优化方法
上面方法中需要新建一个临时变量来存放l1,l2相加的结果,由于是相加,我们考虑开始就将结果指向l1,在l1的基础上进行计算,思路如下:
- 设置结果res=l1,初始化一个进位临时变量carry=0
- 第一阶段l1,l2都有值的时候
- l1.val,l2.val相加并加上上一轮相加的进位carry得到tmpSum,该轮l1.val的值为更新为tmpSum的个位(tmpSum%10),carry更新为tmpSum的十位(tmpSum//10)
- 设定一个临时变量prev指向l1
- l1,l2均指向自己的下一个l1.next,l2.next
- 第一阶段结束时,说明l1,l2有一个已经结束了。这时候把l1设定为还未结束的序列(l1 = l1 or l2),并将临时变量prev.next指向新的l1(为了保证序列的连续性,如果前面没有设置的prev临时变量,那么返回结果就中断了)
- 第二阶段遍历新的l1:
- l1.val加上上一轮的进位carry得到tmpSum,该轮l1.val的值为更新为tmpSum的个位(tmpSum%10),carry更新为tmpSum的十位(tmpSum//10)
- 设定一个临时变量prev指向l1
- l1指向自己的下一个l1.next
- 第二阶段结束后,检查是否还有进位carry,有的话则tmp的下一位为ListNode(1)
- 返回结果:res
完整代码如下:
1 | # Definition for singly-linked list. |
这道题对Python好像不是很友好,经常会出现超时的情况,如果大家有更好的方法,欢迎一起探讨。