题目:两数相加
该题目没有技巧和算法的考察,只是在挑战一些很容易出错的细节问题
right-code
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = ListNode(0)
tmp = head
add_one = 0
while l1 is not None or l2 is not None:
a = l1.val if l1 else 0
b = l2.val if l2 else 0
s = a + b + add_one # 使用s变量承接加和结果,作为下一个节点.val变量的结果凭据
if l1 is not None:
l1 = l1.next
if l2 is not None:
l2 = l2.next
add_one = 1 if s >= 10 else 0 # 进位计算
s = s % 10
tmp.next = ListNode(s)
tmp = tmp.next
if add_one == 1:
tmp.next = ListNode(1)
return head.next
【思路】:
- l1/l2两个链表都空的情况下,结束循环。所以确定外层while循环的条件;
- l1/l2哪个链表为空,就应该把它当成0计算;不为空,就让他next。
- 有进位的情况需要被记录,所以新开一个变量add_one,专门用于记录进位与否;
- 当前节点生成next新节点并移动tmp指针指向;
- 整体循环结束后,若add_one节点是1,则需要在最后补上一个节点。0不需要补。
其实整体流程下来是真简单,但有很多坑到死的小细节,这些地方才是本题精髓:
tmp
指针应指向当前节点。若指向下一个节点,则会导致,当最后一位的加和无需进位时,你没法删除最后一个ListNode(0)
。所以我们一上来就随意初始化一个head头结点,然后最终返回的是head.next
,因为你只有在A节点的前驱节点上的时候,才可以执行A节点的删除/添加操作(通过操作A的前驱节点的.next
指针达成);- 新节点的取值应该新开一个变量存储(line 20)
对比我之前死活提示我“超出时间限制”的代码(下方错误代码“wrong-code”)。我之前的错误代码,就是因为直接修改了tmp.val
参数。要注意,因为实际上tmp
指针是指向当前节点的,而实际上我们计算得到的tmp.val
是下一个节点tmp.next
的取值。所以二者不能等同,直接用tmp.val
接收计算结果(而不是s
),会导致当前节点的.val
参数被修改,这是不对滴
错误代码 wrong-code,未采用新变量存储加和结果
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = ListNode(0)
tmp = head
add_one = 0
while l1 is not None or l2 is not None:
a = l1.val if l1 else 0
b = l2.val if l2 else 0
tmp.val = a + b + add_one # 错误在这里,未使用额外变量s接收加和结果,导致当前节点的.val变量被改动;实际上当前节点的.val参数应该是在tmp指针指向其前驱节点时就已被定义好的。
if l1.next is not None:
l1 = l1.next
if l2.next is not None:
l2 = l2.next
add_one = tmp.val // 10 # 进位计算
tmp.val =int(str(tmp.val)[-1])
tmp.next = ListNode(tmp.val)
tmp = tmp.next
if add_one == 1:
tmp.next = ListNode(1)
return head.next