LeetCode - Sort List

本文详细介绍了如何利用快速排序算法对链表进行排序,确保时间复杂度为O(n log n),同时保持常数空间复杂度。通过定义partition函数,实现链表节点的高效排序,并特别关注了处理链表末尾元素的技巧,以避免不必要的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://leetcode.com/problems/sort-list/

Sort a linked list in O(n log n) time using constant space complexity.

这道题按题目要求就只能用quicksort了,mergesort是需要O(n)额外空间的哈。

先定义partition代码:

以tail的值为seed,比seed小的放左边,比seed大的放右边,最后seed的值和比seed大的这部分里面第一个node交换,保证middle node的值是seed,但是因为在list里面求previous是比较难的,所以返回的不是值为seed的middle node,而是middle node的前一个node, premiddle。

因此下一轮就是

quicksort(head, premiddle);

quickSort(premiddle.next.next, tail);

需要注意的情况是,当中值左边没有的时候,也就是上一次partition中没有比seed小的值时,这时的premiddle返回的是head,也是真正的middle, 所以后半部分排序应该是quickSort(premiddle.next, tail).

当中值右边没有值时,也就是上一次partition中没有比seed大的值时,这里的premiddle是tail前一个node,middle还是tail,但是这时的premiddle.next.next就是不属于当前排序范围了,所以这种情况下就不用排后半部分了。

总之因为Linkedlist排序不像array那样可以比较head,tail的下标,所以在原array中 head>tail可以一下判断出不用再排了,但是在List中head就算到了tail后面,它也可能是个valid的node, 需要考虑这种情况,再处理。

在下面代码的partition函数中,less是middle,pre是premiddle。

代码里面全是值交换,不是node交换,因为node交换需要一个非常完善的swap()函数,容易错。。。不过下次可以试下用node交换。

public class Solution {
    public ListNode sortList(ListNode head) {
        if(head==null || head.next==null) return head;
        ListNode tail = head;
        while(tail.next!=null) tail = tail.next;
        quickSort(head, tail);
        return head;
    }
    
    public void quickSort(ListNode head, ListNode tail){
        if(head == tail || head==null || tail==null) return;
        ListNode premiddle = partition(head, tail);
        
        if(premiddle!=head) quickSort(head, premiddle);
        if(premiddle == head) quickSort(premiddle.next, tail);
        else if(premiddle.next!=tail && premiddle.next.next!=tail) quickSort(premiddle.next.next, tail);
    }
    
    public ListNode partition(ListNode head, ListNode tail) {
        int x = tail.val;
        if(head==tail || head==null || head.next==null) return head;
        ListNode traverse = head;
        ListNode pre = head;
        ListNode less = head;
        while(traverse!=tail){
            if(traverse.val < x){
                int tmp = less.val;
                less.val = traverse.val;
                traverse.val = tmp;
                pre = less;
                less = less.next;
            }
            traverse = traverse.next;
        }
        int tmp = less.val;
        less.val = tail.val;
        tail.val = tmp;
        return pre;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值