2、两数相加
坑爹点:
1、此题代码区会给出给出一段注释,这段注释是为了方便大家理解ListNode这一个类的定义的。LeetCode内置代码已经完成了ListNode这一个类的编写,不需要把这一段取消注释然后直接使用,否则会报错xxx is not valid value for the expected return type ListNode
。
2、两个链表长度不一定相同。
3、输入的链表和输出的链表都是逆序的!
题目给出的三个示例都是顺序和逆序结果相同的。看不仔细就会被坑,比如我。。
简单思路:
1、直接两数相加
就是把链表转换为数,再把两个数求和再转换为链表。
这里用最直观的方式写的,不求时间内存和简洁,只求清晰明白。
上代码:
# 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: ListNode, l2: ListNode) -> ListNode:
number1 = 0
i = 0
while l1 != None:
number1 += l1.val * 10 ** i
l1 = l1.next
i += 1
number2 = 0
i = 0
while l2 != None:
number2 += l2.val * 10 ** i
l2 = l2.next
i += 1
number_out = str(number1 + number2)[::-1]
node = [ListNode() for i in range(len(number_out))]
for i in reversed(range(len(number_out))):
if i == len(number_out)-1:
node[i].next = None
else:
node[i].next = node[i+1]
node[i].val = int(number_out[i])
return node[0]
BinGo!
2、当链表题做
思路一直接求和其实并不太高效,但是重在简单。还可以用链表的方式来做,把两个给定链表每个节点的数相加再构建新链表输出即可。这里要考虑进位和连续进位的情况。
贴一下原代码,非常好理解:
# 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: ListNode, l2: ListNode) -> ListNode:
add_1 = 0 # add_1和add_2是定义的两个进位标志位。1表示下一位置进位,2表示当前节点位置进位。
add_2 = 0
out_list = [] # 定义的输出列表。
while l1 != None or l2 != None or add_2 == 1:
try:
value_1 = l1.val
l1 = l1.next
except AttributeError: # 当无下一节点时取值为0。下同。
value_1 = 0
try:
value_2 = l2.val
l2 = l2.next
except AttributeError:
value_2 = 0
temp = value_1 + value_2 + add_2
if temp >= 10:
add_1 = 1
temp %= 10
out_list.append(temp)
add_2 = add_1 # 节点位置的移动。
add_1 = 0
node = [ListNode() for i in range(len(out_list))]
for i in reversed(range(len(out_list))):
if i == len(out_list)-1:
node[i].next = None
node[i].val = int(out_list[i])
else:
node[i].next = node[i+1]
node[i].val = int(out_list[i])
return node[0]
BinGo!
自己都觉得自己写的太复杂了,下面贴出优化后的思路和代码。
3、优化思路
先上代码,后面给出解析。
# 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: ListNode, l2: ListNode) -> ListNode:
add = 0
result = ListNode()
temp_1 = result
while l1 != None or l2 != None or add == 1:
if l1 != None:
value_1 = l1.val
l1 = l1.next
else:
value_1 = 0
if l2 != None:
value_2 = l2.val
l2 = l2.next
else:
value_2 = 0
temp_2 = ListNode(value_1 + value_2 + add)
add = 0
if temp_2.val >= 10:
add = 1
temp_2.val %= 10
temp_1.next = temp_2
temp_1 = temp_2
return result.next
求和进位都是很简单的操作了,这里主要写一下构造链表的过程,以题目示例1为例来描述一下链表构造中内部各个变量的变化,以此来理清思路。
①初始化 result 变量。
②令 temp_1 指向 result。
③初始化变量 temp_2,其值设定为7。
④使 temp_1.next 指向 temp_2,由于 temp_1和 result 指向同一个内存,temp_1 改变,result 也随之改变。
⑤修改 temp_1的指向,让 temp_1指向 temp_2,即 result.next。
⑥重修初始化 temp_2,其值设定为0。
⑦将temp_1.next 指向 temp_2,相应的,result也会发生改变。
⑧修改 temp_1 ,使 temp_1 指向 temp_2, 即 result.next,next。
⑨重新初始化变量 temp_2,其值设定为8。
⑩、⑪同上重复操作。
⑫返回 result.next 即为所求。
需要注意的是:
Python中如果给变量赋的值是不可变变量,比如整型、字符串、元组,那么是将变量指向这个值所在的内存,对变量进行改变会让变量指向一个新的值的内存地址,而不会改变原内存地址处的值。
比如 a=1, a+=1
这两条语句。第一条语句执行让变量 a 指向 1 所在的内存地址,而第二条语句会让 a 指向 2 所在的内存地址。在这个过程中原来 1 内存地址处存放的还是1。
如下( id() 命令可以获取内存地址):
而如果给变量赋的是可变变量,比如列表、字典、自定义的类(比如上面这个题)等,对变量进行改变会让这个变量指向的内存地址的值发生改变,而不会改变内存地址。
比如 a=[1],a[0]+=1
这两条语句。第一条语句为变量 a 开辟一个新的内存地址,该内存里存放 [1] ,第二条语句会改变这个内存地址里面的值,将 [1] 变成 [2] ,但地址是没有改变的。
如下:
这样也就好解释以下现象的出现:
学霸题,你学会了吗?
这也就是上题中 result
会发生改变的原因。
最后用我形象的比喻来描述一下上面链表创建的过程
这,是一个节点。
形象化一点,节点像不像一块积木(一个独立节点next为空,不妨把这个位置空出来)。
好了,这就是抽象出来的一块积木。比如左图是#号积木。
那么现在就可以玩儿游戏了,如下有三块积木,需要按照7-0-8的顺序拼插在一起。
第一步:一只手按住7号积木,同时准备好0号积木。
第二步:把0号积木插到7号积木的后面。
第三步:手移到0号积木上,按住0号积木;准备好8号积木。
第四步:把8号积木插到0号积木后面。完成拼插。
对比积木拼插过程和上面12张图的链表创建过程,你学会了吗?
填空题:请在以下三个位置填入适当的变量名称(答案见篇尾)。
拓展内容:如果要顺向拼积木怎样操作?
第一步:用手按住7号积木,准备好0号积木。
第二步:把0号积木插在7号积木的前面。
第三步:把手移到0号积木上,按住0号积木;准备好8号积木。
第四步:把8号积木插在0号积木前面,完成拼插。
如下:
# 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: ListNode, l2: ListNode) -> ListNode:
add = 0
temp_2 = ListNode()
while l1 != None or l2 != None or add == 1:
temp_1 = ListNode()
if l1 != None:
value_1 = l1.val
l1 = l1.next
else:
value_1 = 0
if l2 != None:
value_2 = l2.val
l2 = l2.next
else:
value_2 = 0
temp_2.val = value_1 + value_2 + add
add = 0
if temp_2.val >= 10:
add = 1
temp_2.val %= 10
temp_1.next = temp_2
temp_2 = temp_1
return temp_1.next
——————————————————————————————
本文禁止自行转载!盗版必究!