【解一】这个题一看就是个按位加的操作嘛,链表是逆序的所以从头到尾加就相当于从个位开始往高位加了,记得处理进位就行。那麻烦点在哪里呢?人家是链表存的,所以需要准确抓到头和尾巴。l1和l2不一定是等长的,所以长度不够的要在高位补0,那么就相当于每当有一串列表空了,就给它尾巴上补一个(0,None)。终止条件是两串都到底了并且也没有需要进位的。
【ps】这里加两个trick。首先我们两数相加构建了第三个链表,但其实l1和l2加过的节点都没什么用了,所以完全可以直接把结果存进l1里面,这样节省空间。另一个trick就是计算机做加减比做乘除快很多,一般进位操作的写法是{当前位=sum%10;下一位加入sum/10},但两个个位数再包括前面的进位相加,其实范围在0~19之间,特判一下有无进位,比无脑做除法要快。所以我判了一下sum>9的时候l1往后推的同时加个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:
tail = l1
while(1):
sum = l1.val + l2.val
if sum>9:
l1.val = sum % 10
if l1.next == None:
l1.next = ListNode(1,None)
l1 = l1.next
else:
l1 = l1.next
l1.val = l1.val + 1
if l2.next == None:
l2.next = ListNode(0,None)
l2 = l2.next
else: l2 = l2.next
else:
l1.val = sum
if l1.next==None and l2.next==None: break
else:
if l1.next==None: l1.next = ListNode(0,None)
if l2.next==None: l2.next = ListNode(0,None)
l1 = l1.next
l2 = l2.next
return tail
【解二】优化一下,上面的做法每当出现空尾了就补0,这个操作又耗时间又耗空间。我们稍稍做点改动,如果串后面空了就不next了,把当前val变成0就不影响后面算sum。emmm但是提交了一发跟解一的结果没什么区别(尴尬一笑),因为我是存在l1里的,即使l1空尾了也还会为了构造新串加尾巴上去,相当于只优化了一下l2吧= =雀实聊胜于无(至少有心理安慰)。既然只有心理优化那这个代码就懒得放了~ 下一趴吧~
【解三】如何实质性的摆脱补0继续加这件事呢?我们发现这两个链表都是链表呀(废话),那如果有一串后面空了,另一串的尾巴也就没啥要加的了,直接整只续到答案上不就好了么。如果l1后面空了,有进位我就再续一个处理一下进位,没有进位我就next指向l2剩余的元素就可以break了。如果l2后面空了那更方便了,l1后面不需要动了直接break就好了。
(这个交完优化效果就明显了,用时超过99.8%用户,获得了巨大的心理安慰…
# 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:
tail = l1
while(1):
sum = l1.val + l2.val
if sum>9:
l1.val = sum % 10
if (l1.next == None): l1.next = ListNode(0,None)
l1 = l1.next
l1.val = l1.val + 1
if (l2.next != None): l2 = l2.next
else: l2.val = 0
else:
l1.val = sum
if l1.next==None and l2.next==None: break
if l1.next == None:
l1.next = l2.next
break
if l2.next == None: break
l1 = l1.next
l2 = l2.next
return tail