LeetCode —— 148. 排序链表(Python)

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4

示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5

题目要求时间复杂度为O(nlogn),我们考虑使用排序中的归并排序,归并排序有两种排序方法。

第一种是递归形式的归并排序,但是这种方法需要递归操作,所以空间复杂度为O(logn),与题目不符;归并排序的另一种形式为迭代形式,迭代形式不需要进行递归,同时可以根据指向改变链表的拼接顺序,所以只需要常数级的空间就可以完成任务,所以我们使用迭代形式的归并算法进行编程。

class Solution:
    def sortList(self, head: ListNode) -> ListNode:
        h = head  
        length = 0  # 保存链表长度
        intv = 1  # 用于选择将intv的两个链表进行合并
        while h:  # 计算链表长度 
            h = h.next 
            length = length + 1
        res = ListNode(0)  # 伪头部
        res.next = head  # 伪头部后拼接真头部
        
        while intv < length:
            pre = res  # 初始为伪头部
            h = res.next  # 初始为head
            while h:
                
                h1 = h
                i = intv
                while i and h:  # 选择intv长度的一段链表
                    h = h.next
                    i = i - 1
                if i: 
                    break
                    
                h2 = h
                i = intv
                while i and h:  # 选择intv长度的另一段链表
                    h = h.next
                    i = i - 1
                c1, c2 = intv, intv - i  # 因为第二段链表的长度可能不够intv,所以需要进行判断i是否为零,如果不为零则需要减去

                while c1 and c2:  # 将两段链表进行拼接
                    if h1.val < h2.val: 
                        pre.next, h1, c1 = h1, h1.next, c1 - 1
                    else: 
                        pre.next, h2, c2 = h2, h2.next, c2 - 1
                    pre = pre.next
                pre.next = h1 if c1 else h2  # 将排序后仍然剩余的部分拼接,这时候需要将当前头节点进行后移,下面会进行操作
                
                while c1 > 0 or c2 > 0:   # 需要找到新的拼接的链表起点,判断c1或者c2大于0时则需要将链表头节点进行后移
                    pre, c1, c2 = pre.next, c1 - 1, c2 - 1
                    
                pre.next = h 
            intv *= 2  # 迭代长度乘于2
        return res.next

空间复杂度为O(nlogn),时间复杂度为O(1)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值