一.题目要求
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
二.题目难度
中等
三.输入样例
示例 1:
 
 输入:head = [4,2,1,3]
 输出:[1,2,3,4]
示例 2:
 
 输入:head = [-1,5,3,4,0]
 输出:[-1,0,3,4,5]
示例 3:
 输入:head = []
 输出:[]
四.解题思路
解法1:用map按值大小存结点
 解法2:归并排序(GPT)
五.代码实现
解1
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        ListNode* dummy = new ListNode(0);
        map<int,vector<ListNode*>> nodeMap;
        while(head)
        {
            nodeMap[head->val].push_back(head);
            head = head->next;
        }
        ListNode* p = dummy;
        for(auto node : nodeMap)
        {
            for(vector<ListNode*>::iterator it = node.second.begin(); it != node.second.end(); it++)
                {
                    (*it)->next = nullptr;
                    p->next = *it;
                    p = p->next;
                }
        }
        return dummy->next;
    }
};
 
解2
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if (!head || !head->next) return head;
        ListNode* mid = getMid(head);
        ListNode* left = sortList(head);
        ListNode* right = sortList(mid);
        return merge(left, right);
    }
private:
    ListNode* getMid(ListNode* head) {
        ListNode* midPrev = nullptr;
        while (head && head->next) {
            midPrev = (midPrev == nullptr) ? head : midPrev->next;
            head = head->next->next;
        }
        ListNode* mid = midPrev->next;
        midPrev->next = nullptr; // 断开链表
        return mid;
    }
    ListNode* merge(ListNode* list1, ListNode* list2) {
        ListNode dummy(0);
        ListNode* ptr = &dummy;
        while (list1 && list2) {
            if (list1->val < list2->val) {
                ptr->next = list1;
                list1 = list1->next;
            } else {
                ptr->next = list2;
                list2 = list2->next;
            }
            ptr = ptr->next;
        }
        ptr->next = (list1) ? list1 : list2;
        return dummy.next;
    }
};
 
六.题目总结
归并排序在链表排序中非常有效,因为它可以利用链表的节点指针操作,无需像数组那样进行大量的元素交换,其时间复杂度是 O(NlogN),但通常比基于 std::map 的方法更快,因为它具有更好的常数因子和较低的内存使用。
递归分析:
在这里插入代码片
                


















