#21 Merge Two Sorted Lists
You are given the heads of two sorted linked lists
list1
andlist2
.Merge the two lists in a one sorted list. The list should be made by splicing together the nodes of the first two lists.
Return the head of the merged linked list.
解题思路:
分两种,一个是iterative的,另外一个是recursive的。后者的time 和 space complexity都是O(m+n)。前者time complexity是O(m+n),space complexity是O(1)【这里暂时不明白】。
iterative的方法是先排除两个list没有节点的情况,然后比较两个list排头的val大小,小的放入新的list中,然后继续比较后续的节点,直到其中一个list没有节点为止,就把另外一个list剩下的节点接在新list的后面。新的list操作时需要两个pointers,一个是记录整个list,head。另外一个是接最小值用的,tail。
# rule out the possibility of either list1 or list2 is None
if not list1:
if not list2:
return None
else:
return list2
else:
if not list2:
return list1
# create a new linked list
head = ListNode(0)
# attach the smallest nodes from two linked lists to the new one
while list1 and list2:
if list1.val <= list2.val:
# the first node attached to head
if not head.next:
head.next = list1
tail = head.next
# not the first node
else:
tail.next = list1
tail = tail.next
list1 = list1.next
else:
if not head.next:
head.next = list2
tail = head.next
else:
tail.next = list2
tail = tail.next
list2 = list2.next
# when either of the linked list reached to the end
if not list1:
tail.next = list2
else:
tail.next = list1
return head.next
recursive的办法就是假设前面的点都接好了,后面的下一循环也会处理好。只聚焦当前的节点。当前两个list的的节点比较完大小之后,小值当头,头的下一个设置为剩下的节点再进入下一个循环的结果。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
if not list1: return list2
if not list2: return list1
if list1.val <= list2.val:
head = list1
list1.next = self.mergeTwoLists(list1.next, list2)
else:
head = list2
list2.next = self.mergeTwoLists(list2.next, list1)
return head
recursive就理解起来很难,写起来会简洁很多。相当于iterative里的while循环终止条件要放在最前面考虑,套用回自己记得用self.
#2 Add two numbers
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
解题思路:
1.先创建新list的head,连接新节点的tail,以及记录逢十进一的add。
2.然后进入两节点相加的循环处理,只要任一list有节点在,都需要做相加的操作。如果其中一个list已经为None了,那设置其值为0。得到的和,取除以10的余数生成新的节点,连接到新list的tail上。然后list的节点、tail往后移。直到所有节点相加完。
3.最后看add是否为1,是的话就创建值为1的新节点,连接给tail,最后输出head。
# 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: Optional[ListNode], l2: Optional[ListNode], add = 0) -> Optional[ListNode]:
head = ListNode()
tail = head
while l1 or l2:
l1val = 0 if not l1 else l1.val
l2val = 0 if not l2 else l2.val
sum = l1val + l2val + add
val = sum % 10
tail.next = ListNode(val)
add = 1 if sum > 9 else 0
l1 = l1.next if l1 else l1
l2 = l2.next if l2 else l2
tail = tail.next
if add == 1:
tail.next = ListNode(1)
return head.next
本来想用recursive的思路,但写着写着还是变成了iterative。
runtime:
参考了50ms的solution:
发现if add == 1: 那里其实可以合并进入while循环里。实际上加值为1的节点那里可以省略。其他基本一样。
还在forum看到可以合并add 与sum的方法:
创建新节点是val直接是sum%10, 然后add可以改为 sum //= 10。妙喵喵。
recursive的思路
前面还是因为不习惯recursive的思路演算过程,所以还是要强迫自己多练一下。
recursive的思路,参考上一题Merged Two Linked List的思路,先讨论list 1以及list 2都不存在的情况。和iterative的思路正好相反,相当于先思考循环跑完之后,怎么处理。处理步骤从后往前推演。
1.当节点都不在了,而且上一次节点相加之和超过了十的话,那么就还要返回一个新的值为1的节点。如果没有超过十,就什么也不返回。
2.如果只是其中一个list的节点用完了,那么就创建一个ghost值为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: Optional[ListNode], l2: Optional[ListNode], add = 0) -> Optional[ListNode]:
if not l1 and not l2:
if add == 1:
return ListNode(1)
else:
return
if l1:
l1val = l1.val
l1 = l1.next
else:
l1val = 0
if l2:
l2val = l2.val
l2 = l2.next
else:
l2val = 0
sum = l1val + l2val + add
val = sum % 10
head = ListNode(val)
add = 1 if sum > 9 else 0
head.next = self.addTwoNumbers(l1, l2, add)
return head
runtime:
recursive 居然快那么多。amzg.
看到更简洁的解法:
也是和之前看到的iterative的解法一样,把sum和add合并处理了。l2val取值的时候是顺便和l1val相加了。而且用nextSum和两次self.addTwoNumbers,提前处理了逢十进一的情况。tql。真的很难绕过来。再多练吧。