[LeetCode] (medium) 148. Sort List

本文详细介绍了如何在链表上实现归并排序算法,通过迭代和递归两种方式,达到O(n log n)的时间复杂度和常数空间复杂度。文章提供了具体的代码实现,包括断尾重接技巧,以确保在链表上进行高效排序。

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

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

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

Example 1:

Input: 4->2->1->3
Output: 1->2->3->4

Example 2:

Input: -1->5->3->4->0
Output: -1->0->3->4->5

列表排序,还要求nlogn的复杂度,自然想到使用归并排序。

借鉴了别人代码中的“断尾重接”思想,获得了很大的启发 

迭代版:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        int len = 0;
        for(ListNode *cur = head; cur != NULL; cur = cur->next){
            ++len;
        }
        
        //构造头结点
        ListNode *head_node = new ListNode(0);
        head_node->next = head;
        
        for(int interval = 1; interval < len; interval *= 2){
            ListNode *cur_head = head_node;
            ListNode *first, *second;
            do{
                first = cur_head;
                second = cur_head;
                for(int i = 0; i < interval; ++i){
                    if(first != NULL){
                        first = first->next;
                        second = second->next;
                    }else{
                        break;
                    }
                }
                if(first == NULL || first->next == NULL) break; //当前尾部已经落入有序区间
                
                for(int i = 0; i < interval; ++i){
                    if(second != NULL){
                        second = second->next;
                    }else{
                        break;
                    }
                }
                ListNode *next_head = (second == NULL) ? NULL : second->next;   //记录下一个归并区间头指针
                
                //断尾+将first、second定位到头部
                if(second != NULL) second->next = NULL;
                second = first->next;
                first->next = NULL;
                first = cur_head->next;
                
                //归并
                while(first != NULL && second != NULL){
                    if(first->val < second->val){
                        cur_head->next = first;
                        first = first->next;
                        cur_head = cur_head->next;
                    }else{
                        cur_head->next = second;
                        second = second->next;
                        cur_head = cur_head->next;
                    }
                }
                if(first != NULL) cur_head->next = first;
                else cur_head->next = second;
                
                //重连
                while(cur_head->next != NULL){
                    cur_head = cur_head->next;
                }
                cur_head->next = next_head;
                
            }while(cur_head->next != NULL);  //没有后继区间
        }
        
        return head_node->next;
    }
};

递归版:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(head == NULL || head->next == NULL) return head;
        
        ListNode *first = head, *second = head;
        // while(second != NULL && second->next != NULL){
        //这个条件是不行的,因为要确保每一次递归问题规模都要缩小
        //根据后面的代码逻辑,等价于确保first->next != NULL
        //如果使用上述条件,在两个元素的区间下将进入死循环
        //下一行的条件确保了second指针必然不为空,也就确保了first指针之后必然还有元素
        while(second->next != NULL && second->next->next != NULL){
            // cout << second->val << '\t';
            second = second->next->next;
            first = first->next;
        }
        // cout << endl;
        
        second = first->next;
        first->next = NULL;
        
        ListNode *L1 = sortList(head);
        ListNode *L2 = sortList(second);
        return merge_list(L1, L2);
    }
    
    ListNode* merge_list(ListNode *l1, ListNode *l2){
        ListNode *head = new ListNode(0);
        ListNode *cur = head;
        while(l1 != NULL && l2 != NULL){
            if(l1->val < l2->val){
                cur->next = l1;
                l1 = l1->next;
                cur = cur->next;
            }else{
                cur->next = l2;
                l2 = l2->next;
                cur = cur->next;
            }
        }
        cur->next = (l1 == NULL) ? l2 : l1;
        return head->next;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值