21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
代码实现:迭代
# 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, l1: ListNode, l2: ListNode) -> ListNode:
# 基本思路是:两个链表指针一次比较,小的往当前指针后面接,当一个链表为空时,把另一个链表接到后面即可
cur = ListNode(0)
head = cur
while l1 != None or l2 != None:
# 如果链表l1为空
if l1 == None:
cur.next = l2
break
# 如果链表l2为空
if l2 == None:
cur.next = l1
break
if l1.val <= l2.val:
# cur.next = ListNode(l1.val)
cur.next = l1
l1 = l1.next
else:
# cur.next = ListNode(l2.val)
cur.next = l2
l2 = l2.next
cur = cur.next
return head.next
23. 合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
思路:迭代
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
# 合并两个有序链表可以看做是这个问题的子问题
# 基本思路是:链表一直两两合并,最终会合并成一个链表
k = len(lists)
if k == 0:
return None
# 链表两两合并
interval = 1
while interval < k:
# 落单的链表不用管,后面一定会找到配对的
for i in range(0,k,interval*2):
if i + interval < k:
lists[i] = self.mergeTwoLists(lists[i],lists[i+interval])
# 更新步长
interval *= 2
return lists[0]
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
# 基本思路是:两个链表指针一次比较,小的往当前指针后面接,当一个链表为空时,把另一个链表接到后面即可
cur = ListNode(0)
head = cur
while l1 != None or l2 != None:
# 如果链表l1为空
if l1 == None:
cur.next = l2
break
# 如果链表l2为空
if l2 == None:
cur.next = l1
break
if l1.val <= l2.val:
# cur.next = ListNode(l1.val)
cur.next = l1
l1 = l1.next
else:
# cur.next = ListNode(l2.val)
cur.next = l2
l2 = l2.next
cur = cur.next
return head.next
148. 排序链表
给你链表的头结点 head ,请将其按升序排列并返回 排序后的链表 。
进阶:
你可以在 O ( n l o g n ) O(nlogn) O(nlogn) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
示例:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
思路:
这里采用归并排序的方法,其思路图解为:
有没有发现其合并过程跟21题合并两个有序链表一样,只不过是递归调用这个函数
分割、排序环节:首先找到当前链表中点,并从中点将链表断开,以便在下次递归分割排序时,链表片段拥有正确边界:
我们使用fast,slow快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。找到中点slow后,执行slow.next = None
将链表切断。
递归分割时,输入当前链表左端点head和中心节点slow 的下一个节点 mid(因为链表是从slow切断的)。
递归终止条件:当head.next == None
时,说明只有一个节点了,直接返回此节点。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: ListNode) -> ListNode:
# 归并排序
# 递归终止条件
if head == None:
return None
if head.next == None:
return head
# 快慢指针寻找中点,快指针一次走两步,慢指针一次走一步
slow = head
fast = head
while fast.next != None and fast.next.next != None:
slow = slow.next
fast = fast.next.next
# 循环结束时,slow指针指向前面链表的尾结点
mid = slow.next
# 从中点处切断
slow.next = None
# 递归调用这个函数进行拆分
l1 = self.sortList(head)
l2 = self.sortList(mid)
return self.mergeTwoLists(l1,l2)
# 可以使用上面的写法
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
cur = ListNode(0)
head = cur
while l1 != None and l2 != None:
if l1.val <= l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
if l1 == None:
cur.next = l2
else:
cur.next = l1
return head.next
如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!