LeetCode 148.Sort List

题目描述

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

示例1:

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

示例2:

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

思路

1.题目要求时间复杂度为O(nlogn)和O(1)的空间复杂度,因此只能从链表的方向去解决
2.在这种情况下,我们可以用快慢指针将链表一分为二,用递归的方式将链表分解到一个个结点并用链表合并的方式将结点组合起来,这样就生成了一个有序的链表

链表结点结构

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

代码

class Solution:
    def sortList(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
           
        pre, slow, fast = None, head, head
        while fast and fast.next:
            pre, slow, fast = slow, slow.next, fast.next.next
        pre.next = None
        
        return self.merge(*map(self.sortList, (head, slow)))
    
    
    def merge(self, h1, h2):
        dummy = tail = ListNode(None)
        while h1 and h2:
            if h1.val <= h2.val:
                tail.next, h1 = h1, h1.next
            else:
                tail.next, h2 = h2, h2.next
            tail = tail.next
            
        tail.next = h1 or h2
        return dummy.next

代码解释

1.merge函数的作用是将两个链表合并
2.sortList函数里每次将链表一分为二找到中间结点slow
3.将headslow分别作为参数传入sortList进行递归,递归到最底层时返回两个结点
4.将这里两个结点用*作为merge函数的参数
5.这样从递归最底层开始return,最终生成一条有序的链表

复杂度分析

时间复杂度

1.假设用T(n)描述对n个结点的访问
2.找到slow的时间复杂度是O(n),map花费了2 * T(n/2)
3.假设最后合并的两条链表长度都是n/2,则merge的时间复杂度是O(n)
总共T(n) = 2 * T(n/2) + O(n),所以T(n) = O(nlogn)

空间复杂度

dummytail和其他变量用了O(1)的空间,但是递归的时候用了O(logn)的空间,所以这个解法还是有点瑕疵

参考

Clean python code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值