LeetCode 148——排序链表(归并排序)

一、题目介绍

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

示例 1:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、解题思路

利用归并排序完成该题目,因为是对链表排序,所以不需要引入太多的额外空间。归并排序分为以下三步:

(1)计算链表长度

(2)自底向上分割链表,先按照长度为2^0分割,再按照2^1分割,再按照2^2分割,以此类推……

(3)每次分割之后,需要将分割后的链表,有序合并。

三、解题代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* cut(ListNode* node, int n) //以node为起点切掉n个节点,返回剩下链表的表头
    {
        ListNode* p = node;
        while(--n && p)
        {
            p = p->next;
        }
        if(p == NULL)
            return NULL;
        ListNode* next = p->next;
        p->next = NULL;
        return next;
    }
    
    ListNode* merge(ListNode* l, ListNode* r)
    {
        ListNode* node = new ListNode(0);
        ListNode* p = node;
        while(l && r)
        {
            if(l->val < r->val)
            {
                p->next = l;
                l = l->next;
            }
            else
            {
                p->next = r;
                r = r->next;
            }
            p = p->next;
        }
        p->next = l == NULL ? r: l;
        return node->next;
    }
    
    ListNode* sortList(ListNode* head) {
        ListNode* newHead = new ListNode(0);
        newHead->next = head;
        ListNode* pTemp = head;
        //计算链表长度
        int len = 0;
        while(pTemp)
        {
            len++;
            pTemp = pTemp->next;
        }
        
        //归并排序
        for(int i = 1; i < len; i *= 2)
        {
            ListNode* tail = newHead;
            ListNode* cur = newHead->next;
            //首先按照长度为1切分链表,再合并;再按照长度为2^1切分链表,再合并,依次类推……
            while(cur)
            {
                ListNode* left = cur;  //left->@->@->null  左链表
                ListNode* right = cut(left, i);  //右链表 right->@->@->null
                cur = cut(right, i); // cur->@->@->null
                tail->next = merge(left, right);  //合并两个链表
                while(tail->next)
                    tail = tail->next;
            }
        }
        return newHead->next;
    }
};

四、解题结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值