leetcode_效率题解_148. Sort List_(链表归并排序)

本文探讨如何使用归并排序在O(n log n)的时间复杂度内对链表进行排序,同时提供了链表插入排序的题解。通过特定的指针技巧找到链表的中点,实现高效排序。此外,还提及了快速排序在链表操作中的应用。

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

相关题解:
leetcode_效率题解_[python/C++]_147. Insertion Sort List(链表插入排序)

题目链接
【题目】
Sort a linked list in O(n log n) time using constant space complexity.
这里写图片描述
【分析】
O(nlogn)的复杂度我们很显然想到归并排序,快速排序


记得大一的时候写链表排序的题都是先转成数组或者vector然后再进行排序,贴出来以便大家熟悉一下数组的归并排序

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if( head == NULL ) return head;
        vector<int> vec;
        while( head != NULL ){
            vec.push_back(head->val);
            head = head->next;
        }
        int size = vec.size();
        merge_sort( vec , 0 , size - 1 );
        ListNode * List = new ListNode(vec[0]);
        ListNode * ans = List;
        for( int i = 1 ; i < size ; i ++ ){
            ListNode * temp = new ListNode(vec[i]);
            ans->next = temp;
            ans = ans->next;
        }
        return List;

    }
    void merge( vector<int>& a , int low , int mid , int high ){
        vector<int> temp( high - low + 1 , 0 );
        int i = low , j = mid+1 , m = mid , n = high , k = 0;
        while( i <= m && j <= n ){
            if( a[i] < a[j] ) temp[k++] = a[i++];
            else temp[k++] = a[j++];
        }
        while( i <= m ) temp[k++] = a[i++];
        while( j <= n ) temp[k++] = a[j++];
        for( int g = 0 ; g < k ; g ++ ) a[low+g] = temp[g];
    }
    void merge_sort( vector<int>& a , int low , int high ){
        if( low < high ){
            int mid = ( low + high )/2;
            merge_sort( a , low , mid );
            merge_sort( a , mid+1 , high );
            merge( a , low , mid , high );
        }
    }
};

然而效率是这样的
这里写图片描述
所以归根到底我们还是得用指针来写:
那重点在哪里呢,在于如何找到一个链表的mid
这里我用了下面一段代码来找到分界点second_head

ListNode * slow = head;
        ListNode * fast = head->next;
        while(fast&&fast->next){
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode * second_head = slow->next;
        slow->next = NULL;

所以就简单了:

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if( !head || !head->next ) return head;
        ListNode * slow = head;
        ListNode * fast = head->next;
        while(fast&&fast->next){
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode * second_head = slow->next;
        slow->next = NULL;
        return merge( sortList(head) , sortList(second_head) );
    }
    ListNode * merge( ListNode * left , ListNode * right ){
        ListNode * new_list = new ListNode(0);
        ListNode * temp = new_list;
        while( left && right ){
            if( left->val < right->val ){
                temp=temp->next = left;
                left = left->next;
            }
            else{
                temp = temp->next = right;
                right = right->next;
            }
        }
        if( left ) temp->next = left;
        else temp->next = right;
        return new_list->next;
    }

};

效率就是最前面的runtime
当然merge函数也可以这样写,效率也一样的

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if( !head || !head->next ) return head;
        ListNode * slow = head;
        ListNode * fast = head->next;
        while(fast&&fast->next){
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode * second_head = slow->next;
        slow->next = NULL;
        return merge( sortList(head) , sortList(second_head) );
    }
    ListNode * merge( ListNode * left , ListNode * right ){
        ListNode * new_list = new ListNode(0);
        ListNode * temp = new_list;
        while( left || right ){
            if( left && ( !right || left->val < right->val ) ){
                temp = temp->next = left;
                left = left->next;
            }
            if( right && ( !left || left->val >= right->val ) ){
                temp = temp->next = right;
                right = right->next;
            }
        }
        temp->next = NULL;
        return new_list->next;
    }

};

至于快速排序,有点难想,就贴一个网上的写法:

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        ListNode* tail;
        quickSort(head,tail);
        return head;
    }
private:
    void quickSort(ListNode* &head,ListNode* &tail){
        if(head==nullptr)
            return;
        ListNode left_head(-1),right_head(-1);
        ListNode *left_tail=&left_head,*right_tail=&right_head;
        ListNode *pivot_head=head,*pivot_tail=head,*now=head->next;
        int key=pivot_head->val;
        //paritition
        while(now!=nullptr){
            if(now->val < key){
                left_tail->next=now;
                left_tail=now;
            } else if(now->val > key){
                right_tail->next=now;
                right_tail=now;
            } else {
                pivot_tail->next=now;
                pivot_tail=now;
            }
            now=now->next;
        }

        //deal with end node
        right_tail->next=nullptr;
        left_tail->next=nullptr;
        pivot_tail->next=nullptr;

        quickSort(left_head.next,left_tail);
        quickSort(right_head.next,right_tail);
        //connect pivot,sorted left part,sorted right part
        if(left_head.next!=nullptr && right_tail!=&right_head){
            //left part and right part is not null
            //L->P->R
            left_tail->next=pivot_head;
            pivot_tail->next=right_head.next;
            head=left_head.next;
            tail=right_tail;

        } else if(left_head.next!=nullptr){
            //left part is not null but right part is null
            //L->P
            left_tail->next=pivot_head;
            head=left_head.next;
            tail=pivot_tail;
        } else if(right_tail!=&right_head){
            //right part is not null but left part is null
            //P->R
            pivot_tail->next=right_head.next;
            head=pivot_head;
            tail=right_tail;
        }
        //no need to deal with two null situation.
    }
};
安装Docker安装插件,可以按照以下步骤进行操作: 1. 首先,安装Docker。可以按照官方文档提供的步骤进行安装,或者使用适合您操作系统的包管理器进行安装。 2. 安装Docker Compose插件。可以使用以下方法安装: 2.1 下载指定版本的docker-compose文件: curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose 2.2 赋予docker-compose文件执行权限: chmod +x /usr/local/bin/docker-compose 2.3 验证安装是否成功: docker-compose --version 3. 在安装插件之前,可以测试端口是否已被占用,以避免编排过程中出错。可以使用以下命令安装netstat并查看端口号是否被占用: yum -y install net-tools netstat -npl | grep 3306 现在,您已经安装Docker安装Docker Compose插件,可以继续进行其他操作,例如上传docker-compose.yml文件到服务器,并在服务器上安装MySQL容器。可以参考Docker的官方文档或其他资源来了解如何使用DockerDocker Compose进行容器的安装和配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Docker安装docker-compose插件](https://blog.csdn.net/qq_50661854/article/details/124453329)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Docker安装MySQL docker安装mysql 完整详细教程](https://blog.csdn.net/qq_40739917/article/details/130891879)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值