版权申明:原创文章,未经博主同意,不得转载!
Add Two Numbers(两数相加),这是一道关于链表的题目,其内容如下:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807
可以看到这道题目并不困难,对于新手来说,解决的主要问题有两个,一在于链表数据类型的操作,这一点可能有的人比较陌生,二是对各种可能出现情况考虑的完备性,也就是算法是否能够通过各种特殊情况的测试。关于链表数据类型,感兴趣的同学可以点击链表。
下面,我们简要的说明一下算法思路。
由于这道题目给定的数字顺序是从低位到高位的,这样就避免了顺序问题,而且每个结点只有一位非负整数。所以只需将两个链表中的元素逐位取出直接相加,考虑到进位情况,新链表对应位置存储个位数,设置进位标志参与下一位的运算,当结束后返回新链表就可以了。如下图给出的示例计算过程。
具体的做法就是先建立一个新链表,保存新链表的头部用于返回,之后同步遍历给定的两个非空链表,在没有到达某一个链表最后一个结点之前,将两个链表的值相加,结果保留下来。这个题目的关键点在于对到达最后结点的链表如何处理。我们初步的思路是在两个链表都未到最后一个结点时,同步遍历计算结果。当一个链表到达最后结点后,结束同步遍历,仅对没有到达最后结点的链表进行处理。为了避免出现999…9 + 1这种连续进位的情况,在处理单链表是也需要保留进位。当处理完两个链表相加后,我们最后还需要处理最后一次相加的进位,因为两个十以内的数相加,带上进位最大也就是9+9+1 = 19这种情况,因此,进位非0即1,当进位为1时,在结果链表最后在建立一个结点保存,无进位就不用处理。我们的代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 创建新链表存储结果
l3_start = ListNode(0)
l3 = l3_start
# 进位标志
carry = 0
# l1和l2都没有到最后一个结点
while l1 and l2:
l3.next = ListNode((l1.val + l2.val + carry) % 10)
carry = (l1.val + l2.val + carry) // 10
# 取链表的下一个结点
l1 = l1.next
l2 = l2.next
l3 = l3.next
# l1没有到达最后一个结点
if l1:
# 只计算l1和进位
while l1:
l3.next = ListNode((l1.val + carry) % 10)
carry = (l1.val + carry) // 10
l1 = l1.next
l3 = l3.next
# l2没有到达最后一个结点
if l2:
# 只计算l2和进位
while l2:
l3.next = ListNode((l2.val + carry) % 10)
carry = (l2.val + carry) // 10
l2 = l2.next
l3 = l3.next
# 处理进位
if carry == 1:
l3.next = ListNode(1)
# 返回链表起点
return l3_start.next
提交运行结果如下:
哈哈,结果还是可以的。
我们去看一下速度最快的代码是什么样子的。
后来看了官网给出的解答,这个代码的思路是按照如下思路写的:
按照官方给定的伪代码,我们也编写了对应的代码。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 创建新链表存储结果
l3_start = ListNode(0)
l3 = l3_start
# 进位标志
carry = 0
# l1和l2均为到达最后一个结点
while l1 or l2:
# 到达最有一个结点的链表对应的数值赋为0
x = l1.val if l1 else 0
y = l2.val if l2 else 0
# 计算和
s = x + y + carry
# 为新结点设定值
l3.next = ListNode(s % 10)
# 保留进位
carry = s // 10
# 指向下一个结点
l3 = l3.next
# 达最后一个结点的链表不在更新位置
if l1:
l1 = l1.next
if l2:
l2 = l2.next
# 处理最后的进位
if carry == 1:
l3.next = ListNode(1)
# 返回链表起点
return l3_start.next
提交结果如下。
可以看到,运行速度还是很快的。
这道AddTwoSum的解法就介绍到这里。
以上。
本期到此结束,扫下面二维码加Python学习公众号,有海量优质学习资源!