LeetCode 148. 排序链表

题目描述

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

进阶:
你可以在 \(O(n \log n)\) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

示例1:

输入:head = [4,2,1,3]
输出:[1,2,3,4]

示例2:

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

示例3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目在范围 [0, 5 * 104]
  • -105 <= Node.val <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list

思路解析

排序的算法有很多,简单的排序算法有类似LeetCode 147 对链表进行插入排序。这里要求时间复杂度为 \(O(n\log n)\),需要考虑稍微快一些的排序算法,这里采用归并排序。
归并排序并不复杂,但是与常见的数组排序不同,数组排序可以在 \(O(1)\) 的时间内找到数组的中点,并进行递归。但是在链表中需要找到中点,无法通过 \(O(1)\) 的复杂度直接查询得到。

这里采用 快慢指针 的方法来查找链表中点,定义 快指针 和 慢指针,快指针每次移动两格,慢指针每次移动一格,快指针移动至末尾时,慢指针移动至中点。这里可能需要细心一些来保证快慢指针不出错。

代码实现

class Solution {
private:
    ListNode* mergeList(ListNode* h1, ListNode* h2) {
        ListNode* dhead = new ListNode();
        ListNode* p1 = h1;
        ListNode* p2 = h2;
        ListNode* p = dhead;
        while(p1 && p2) {
            if(p1->val < p2->val) {
                p->next = p1;
                p = p1;
                p1 = p1->next;
            }
            else {
                p->next = p2;
                p = p2;
                p2 = p2->next;
            }
        }
        if(p1) p->next = p1;
        else if(p2) p->next = p2;
        return dhead->next;
    }
    ListNode* mergeSort(ListNode* head) {
        if((!head) || (!head->next)) return head;
        ListNode* mid = head;
        ListNode* fast = head;
        while(fast && fast->next) {
            fast = fast->next;
            if(!fast->next) break;
            fast = fast->next;
            mid = mid->next;
        }
        ListNode* h1 = head;
        ListNode* h2 = mid->next;
        mid->next = nullptr;
        return mergeList(mergeSort(h1), mergeSort(h2));
    }
public:
    ListNode* sortList(ListNode* head) {
        return mergeSort(head);
    }
};
/**
 * 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) {}
 * };
 */
posted @ 2020-11-21 19:39  行者橙子  阅读(145)  评论(0编辑  收藏  举报