LeetCode0148.排序链表 Go语言AC笔记

 时间复杂度:O(n logn),空间复杂度:O(1)

解题思路

一定要用空间复杂度为O(1)的方法解题,不然面试官极有可能让你优化代码!

要求时间复杂度为O(n logn),那一定就会想到二分排序法。数组中最常用的排序方法就是快速排序,但在链表中最常用的排序方法是归并排序,不过归并排序也分为两种,一种是通过递归自顶向下归并,另一种是自底向上的归并。对于前者空间复杂度取决于递归栈,而后者的空间复杂度为O(1),所以该题我们选择用自底向上的归并排序解题。

思路其实很简单,先统计链表的总长度,然后先根据长度为1划分链表,按顺序合并两个划分部分,合并后长度为2且有序。当所有划分部分合并后,根据长度2划分链表……重复以上步骤,每次划分长度都翻倍。

这样当划分长度大于等于链表长度时就说明我们已经排序好了整个链表,可以返回结果了。

对于如何合并两个有序链表,可以参考我之前写的“21.合并两个有序链表”题解。

LeetCode0021.合并两个有序链表 Go语言AC笔记https://blog.csdn.net/Hexa_H/article/details/127278986

AC代码

整体参考的官方题解代码,并进行了小小的优化,时间效率高一些。

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func sortList(head *ListNode) *ListNode {
    res:=&ListNode{Next:head}
    length:=0
    for head!=nil{
        length++
        head=head.Next
    }
    for l:=1;l<length;l<<=1{
        pre,cur:=res,res.Next
        for cur!=nil{
            head1:=cur
            for i:=1;i<l&&cur.Next!=nil;i++{
                cur=cur.Next
            }
            head2:=cur.Next
            if head2==nil{
                pre.Next=head1
                break
            }
            cur.Next=nil
            cur=head2
            for i:=1;i<l&&cur.Next!=nil;i++{
                cur=cur.Next
            }
            next:=cur.Next
            cur.Next=nil
            pre.Next=merge(head1,head2)
            if next==nil{
                break
            }
            for pre.Next!=nil{
                pre=pre.Next
            }
            cur=next
        }
    }
    return res.Next
}

func merge(a,b *ListNode)*ListNode{
    res:=&ListNode{-1,nil}
    p:=res
    for a!=nil&&b!=nil{
        if a.Val<b.Val{
            p.Next=a
            a=a.Next
        }else{
            p.Next=b
            b=b.Next
        }
        p=p.Next
    }
    if a==nil{
        p.Next=b
    }
    if b==nil{
        p.Next=a
    }
    return res.Next
}

感悟

链表里最常用的排序算法就是归并排序,其中自底向上的归并排序空间复杂度为O(1),务必要掌握。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SwithunH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值