题目描述
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
解题思路
本题其实是让用归并排序的思想对链表进行排序,分为两个阶段:首先将整个链表分为两部分,一般是从中间切开,对两部分分别进行排序;然后将两个排序好的链表合并成一个链表。下面分别对两步进行分析:
- 将链表分为两部分时,要首先找到中间节点,考虑用快慢指针的方法,快指针每次走两步,慢指针每次走一步,这样当快指针无路可走即下两步出现空指针时,慢指针正好处于链表中间节点。然后从慢指针后把整个链表切成两半,两部分再分别进行递归排序
- 将两个排序链表合并时,首先初始化一个伪头节点,用其next指针指向新链表的头节点。从两个排序链表的头节点开始比较,每次将值较小的节点拼接到新链表后,若遇到其中一个节点为空则将另一个链表拼接到新链表后,这样遍历到两个链表末尾,最后返回伪头节点的next指针
代码
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode* sortList(ListNode* head) { 12 if(head == NULL || head->next == NULL) 13 return head; 14 ListNode *quick = head, *slow = head; 15 //快慢指针找到中间节点 16 while(quick->next && quick->next->next){ 17 quick = quick->next->next; 18 slow = slow->next; 19 } 20 quick = slow; 21 slow = slow->next; 22 quick->next = NULL; 23 ListNode *first = sortList(head); 24 ListNode *second = sortList(slow); 25 return mergeList(first, second); 26 } 27 ListNode* mergeList(ListNode* first, ListNode* second){ 28 ListNode node(-1); 29 ListNode *p = &node; 30 while(first != NULL || second != NULL){ 31 int val1 = first == NULL ? INT_MAX : first->val; 32 int val2 = second == NULL ? INT_MAX : second->val; 33 if(val1 < val2){ 34 p->next = first; 35 first = first->next; 36 } 37 else{ 38 p->next = second; 39 second = second->next; 40 } 41 p = p->next; 42 } 43 return node.next; 44 } 45 };