148.排序链表

这篇博客介绍了如何使用归并排序算法在O(nlogn)的时间复杂度和常数级空间复杂度下对链表进行排序。通过定义慢指针和快指针找到链表中间节点,然后递归地对两个子链表进行排序,并最终合并成有序链表。代码中展示了具体的实现细节,包括如何拆分链表、如何排序子链表以及如何合并两个已排序的链表。
摘要由CSDN通过智能技术生成

排序链表

题目

给你链表的头结点 head ,请将其按升序排列并返回排序后的链表 。
进阶:
你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

示例1

输入:head = [4,2,1,3]
输出:[1,2,3,4]

示例2

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

示例3

输入:head = []
输出:[]

解题思路

排序的题目且在时间复杂度为O(nlogn)下完成排序,则时间复杂度为O(nlogn)的排序算法有归并排序、快速排序(快速排序的最差时间复杂度为O(n^2))、堆排序,此题用归并排序最为合适。最容易想到的是自顶向下的递归实现,考虑递归调用的栈空间,自顶向下的归并排序需要O(nlogn)的空间复杂度,此题需要O(1)的空间复杂度,则需要自底向上的归并排序。自底向上的归并方法后面我再写。
归并排序(自上而下)

  1. 找到链表的中间节点并断开为两个子链表,此题找中间节点可用快慢指针方法,定义一个慢指针slow=head,快指针fast=head.next,慢指针走一步,快指针走两步,由于快指针走的距离是慢指针的两倍,故当快指针走到最后一个节点时,慢指针刚好走到中间节点,则mid=slow.next,再令slow.next=None,断开链表
  2. 对两个子链表分别排序(两个子链表同样再继续从中间断开,依次类推直到拆分为一个节点为止,然后再两两合并排序,最后结果则为两个有序链表)
  3. 对两个排序好的子链表进行合并排序,方法和合并两个有序链表方法一样
代码
class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
        
class Solution(object):
    def sortList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if (not head) or (not head.next):
        	return head
        slow = head
        fast = head.next
        while fast and fast.next:
        	slow = slow.next
        	fast = fast.next.next
        mid = slow.next
        slow.next = None
        return self.mergeList(self.sortList(head), self.sortList(mid))
	def mergeList(self, node1, node2):
		r = ListNode()
		q = r
		while node1 and node2:
			if node1.val <= node2.val:
				r.next = node1
				node1 = node1.next
			else:
				r.next = node2
				node2 = node2.next
			r = r.next
		r.next = node1 if node1 else node2
		return q.next
		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值