题目描述:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
转自:力扣(LeetCode)
题目分析:
根据题目,我们要复习关于链表的基础知识,链表作为数据结构的基本
非线性数据结构,主要有数据(val)和指针(next)构成,我们可以再python中
用类来定义一个基础的链表结构:
通过类定义一个初始状态为NoneNoneNone的数据节点:
class ListNode():
def __init__(self,x):
self.val=x
self.next=None
在定义完链表的数据结构后,我们可以开始解题:我们要考虑如下几个问题:
- 如何高效的解决相加数字的位数问题?例如三位数和二位数相加.
- 如何解决进位问题
- 如何解决链表节点为None 报错问题
我们从解决以上三个问题来展开我们的论述:
问题解决
位数问题:
开始时考虑通过判断语句来分别构建不同位数情况,但是无论什么情况下,用到判断语句会让情况变得复杂,让代码变得冗长无效,所以我们考虑用循环语句来解决位数问题,两数相加,我们无论如何都会加到最高位,较低位数字在高位置0:通过如下代码表示我们需要表示的含义:
#l1,l2是含有不同节点的链表
while(l1 or l2): #这句代码的意思是,循环到l1,l2的最高位
x=l1.val if l1 else 0
y=l2.val if l2 else 0 #这里我为什么要以l1和l2为判断条件呢?
#因为我上面提到的第三个问题,如果链表节点为None的话,我们直接
#调用链表的属性会报错,所以链表的判断中,我们需要以它本身而不是
#它的属性来判断,避免出错
if (l1!=None):
l1=l1.next
if(l2!=None):
l2=l2.next
进位问题
我们用carrycarrycarry来表示进位,通过//////整数除法来确定carry的值,因此我们在上面的基础加入进位:
carry=0
a=ListNode(0)
while(l1 or l2):
x=l1.val if l1 else 0
y=l2.val if l2 else 0
res=x+y+carry
s=ListNode(res%10)
a.next=s
carry=res//10
if (l1!=None):
l1=l1.next
if(l2!=None):
l2=l2.next
a=a.next
进一步考虑
如果发生最高位进位的情况会怎么样呢?我们需要在之前的代码上加上一个判断条件,如果最后一次进位不为0,我们就需要在所求链表的尾部加入进位值 。
if carry!=0:
a.next=ListNode(carry)
但是这时候还会发生一个问题,我们的结果链表aaa在一边遍历一遍赋值.等赋值完后,链表已经到了表尾,这时候返回的链表不是我们需要的,我们需要通过隐形复制链表BBB来让链表BBB充当边赋值边遍历的过程,我们通过返回被复制的链表作为我们的结果。
完整代码
# 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):
s=ListNode(0)
a=s
carry=0
while(l1 or l2):
x=l1.val if l1 else 0 #当它跳到val的时候,如果l为节点且为空的话 就会报错
y=l2.val if l2 else 0
res=ListNode((x+y+carry)%10)
a.next=res
carry=(x+y+carry)//10 #整数除法
a=a.next
if (l1!=None):
l1=l1.next
if (l2!=None):
l2=l2.next
if carry!=0:
a.next=ListNode(1)
return s.next
总结
- 因为我们定义的默认next=None,所以链表要用节点来判断,因为节点要么位None 要么为class ,不要用节点的属性来判断,当节点为None时,用属性判断会报错。
- .然后这个是常规的位数相加问题,只不过套上了链表的外皮,但是本质是一样,是进位和相应位数的数字相加,我们需要考虑多种情况,例如最高位进位的问题,不同位数的问题。
- 一个隐形复制的问题也比较有趣,我们让a=sa=sa=s,然后让aaa代替sss边遍历边复制,a的值也会相应的复制到s,也就是所谓的隐形复制,复制的值变也为导致被复制的值变化。