code21. Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Example:
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4
解答:
- 临界:l1.val与l2.val的大小比较决定较小的一方置入新的链表中
- 边界:当l1为空或l2为空。直接将另一方的剩余链表接在新的链表后面。
代码:
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
new_node = ListNode(0)
operate = new_node
while True:
if l1 == None:
operate.next = l2
return new_node.next
elif l2 == None:
operate.next = l1
return new_node.next
elif l1.val <= l2.val:
operate.next = ListNode(l1.val)
l1 = l1.next
operate = operate.next
elif l1.val > l2.val:
operate.next = ListNode(l2.val)
l2 = l2.next
operate = operate.next
这么多判断不够美观,现在可以优化代码(但是时间复杂度基本差不多)
- 对于边界为空的时候,可以使用 operate.next = l1 if l1 else l2
- 对于中间情况的循环,之前使用的是True,结束return跳出循环,现在直接进行l1 和 l2的判断,空就跳出。跳出以后再接 1 中的边界。
优化后的代码:
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
new_node = ListNode(0)
operate = new_node
while l1 and l2:
if l1.val <= l2.val:
operate.next = l1
l1 = l1.next
else:
operate.next = l2
l2 = l2.next
operate = operate.next
operate.next = l1 if l1 else l2
return new_node.next
**
code23:合并K个有序链表
**
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
承接上一题,这里想到一个调用方法,先合并12 再合并13,最后直到1 k-1.
代码:
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
k = len(lists)
if k == 0:
return
else:
res = lists[0]
for i in range(k-1):
res = self.mergetwo(res,lists[i+1])
return res
def mergetwo(self,l1,l2):
new_node = ListNode(0)
operate = new_node
while l1 and l2:
if l1.val <= l2.val:
operate.next = l1
l1 = l1.next
else:
operate.next = l2
l2 = l2.next
operate = operate.next
operate.next = l1 if l1 else l2
return new_node.next
有更好的方法:使用优先队列(PriorityQueue)或者堆(heap)
但是leetcode 的链表块不支持__it__ 方法(这是一个比较方法)
理解这个意思就可以了。
- 定义优先队列或者堆(有自动调用最小值的方法)
- 将K个链表的head以及其value放进去
- 获取最小值及其node,将node接到operate.next 然后node,operate遍历到下一个节点
- 考虑node为空的话(已经到了next了),那就不要了直接进入下一层循环;如果不为空,就将其值和node再放入优先队列或者堆中 继续循环。
- 指导全空后,返回new_node.next。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
from queue import PriorityQueue
class Solution:
def mergeKLists(self,lists):
myqueue = PriorityQueue()
for l in lists:
myqueue.put((l.val,l))
new_node = operate = ListNode(0)
while not myqueue.empty():
value, linked = myqueue.get()
operate.next = linked
operate = operate.next
linked = linked.next
while linked != None:
myqueue.put((linked.val,linked))
return new_node.next
import heapq
class Solution:
def mergeKLists(self,lists):
myheap = []
myheap = heapq.heapify(myheap)
for l in lists:
heapq.heappush(myheap,(l.val,l))
new_node = operate = ListNode(0)
while myheap:
value, linked = heapq.heappop()
operate.next = linked
operate = operate.next
linked = linked.next
while linked !=None:
heapq.heappush(myheap,(linked.val,linked))
return new_node.next
根据评论区大佬留言:
自定义wrapper类附带__it__方法可以做到带入时自己比较大小。
from queue import PriorityQueue
class Solution():
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
class Wrapper():
def __init__(self, node):
self.node = node
def __lt__(self, other):
return self.node.val < other.node.val
head = point = ListNode(0)
q = PriorityQueue()
for l in lists:
if l:
q.put(Wrapper(l))
while not q.empty():
node = q.get().node
point.next = node
point = point.next
node = node.next
if node:
q.put(Wrapper(node))
return head.next