leetcode 148. 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

Example 3:

Input: head = []
Output: []

Constraints:

  • The number of nodes in the list is in the range [0, 5 * 104].
  • -105 <= Node.val <= 105

题目难度:简单(递归式归并),中等(非递归归并)

题目大意:给一个链表排序,并要求常数空间复杂度$O(1)$,$O(nlogn)时间复杂度$

思路:常用的快排和归并排序,快排在有些情况下的时间复杂度是$(n^2)$,在链表情况下不方便。选择第一个节点为枢纽值。

归并排序时间复杂度是$O(nlogn)$,用递归方法实现的方法,空间复杂度是O(logn)(栈)。所以按照提议应该选择迭代式的归并排序,可以实现$O(1)$空间复杂度(由于是链表,在归并的时候可以不用先new数组作为辅助)。


版本一:递归式的归并排序C++代码:

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode() : val(0), next(nullptr) {}
 7  *     ListNode(int x) : val(x), next(nullptr) {}
 8  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 9  * };
10  */
11 class Solution {
12 private:
13     //合并两个有序链表
14     ListNode* mergeList(ListNode *front, ListNode *rear) {
15         ListNode *res = new ListNode(0), *tail = res;
16         ListNode *tmp1 = front, *tmp2 = rear;
17         while ((nullptr != tmp1) && (nullptr != tmp2)) {
18             if (tmp1->val <= tmp2->val) {
19                 tail->next = tmp1;
20                 tail = tmp1;
21                 tmp1 = tmp1->next;
22             } else {
23                 tail->next = tmp2;
24                 tail = tmp2;
25                 tmp2 = tmp2->next;
26             }
27             tail->next = NULL;
28         }
29         if (nullptr != tmp1)
30             tail->next = tmp1;
31         else
32             tail->next = tmp2;
33         return res->next;
34     }
35     //找到后一半链表,并返回后一半链表的头指针,同时将前一半链表的尾结点指针指向NULL。
36     ListNode* splitList(ListNode *head) {
37         ListNode *midPrev = head, *fast = head->next;
38         //采用快慢指针的方法找到链表中点
39         while ((nullptr != fast) && (nullptr != fast->next)) {
40             fast = fast->next->next;
41             midPrev = midPrev->next;
42         }
43         ListNode *mid = midPrev->next;
44         midPrev->next = nullptr;
45         return mid;
46     }
47     // void printList(ListNode *head) {
48     //     if (nullptr == head) return;
49     //     cout << head->val;
50     //     ListNode *tmp = head->next;
51     //     while (nullptr != tmp) {
52     //         cout << "->" << tmp->val;
53     //         tmp = tmp->next;
54     //     }
55     //     cout << endl;
56     // }
57 public:
58     ListNode* sortList(ListNode* head) {
59         if ((head == nullptr) || (head->next == nullptr)) return head;
60         ListNode *rear = splitList(head); //找到后一半链表
61         // printList(head);
62         // printList(rear);
63         ListNode *head1 = sortList(head); //将前一半链表排好序
64         // printList(head1);
65         ListNode *head2 = sortList(rear); //将后一半链表排好序
66         // printList(head2);
67         return mergeList(head1, head2); //合并两个排好序的链表,并返回。
68     }
69 };

版本二:迭代式的归并排序C++代码:

 1 class Solution {
 2 private:
 3     ListNode* split(ListNode *start, int size) {
 4         ListNode* midPrev = start;
 5         ListNode* end = start->next;
 6         for (int index = 1; index < size && (midPrev->next || end->next); ++index) {
 7             if (end->next) {
 8                 end = (end->next->next) ? end->next->next : end->next;
 9             }
10             if (midPrev->next) {
11                 midPrev = midPrev->next;
12             }
13         }
14         ListNode *mid = midPrev->next;
15         nextSubList = end->next;
16         midPrev->next = nullptr;
17         end->next = nullptr;
18         return mid;
19     }
20     
21     //合并两个有序链表
22     void mergeList(ListNode *front, ListNode *rear) {
23         ListNode *res = new ListNode(0), *newTail = res;
24         ListNode *tmp1 = front, *tmp2 = rear;
25         while ((nullptr != tmp1) && (nullptr != tmp2)) {
26             if (tmp1->val <= tmp2->val) {
27                 newTail->next = tmp1;
28                 newTail = tmp1;
29                 tmp1 = tmp1->next;
30             } else {
31                 newTail->next = tmp2;
32                 newTail = tmp2;
33                 tmp2 = tmp2->next;
34             }
35             newTail->next = NULL;
36         }
37         if (nullptr != tmp1)
38             newTail->next = tmp1;
39         else
40             newTail->next = tmp2;
41         while (newTail->next) {
42             newTail = newTail->next;
43         }
44         tail->next = res->next;
45         tail = newTail;
46     }
47     int gCount(ListNode *head) {
48         int cnt = 0;
49         ListNode *tmp = head;
50         while (nullptr != tmp) {
51             ++cnt;
52             tmp = tmp->next;
53         }
54         return cnt;
55     }
56     // void printList(ListNode *head) {
57     //     if (nullptr == head) return;
58     //     cout << head->val;
59     //     ListNode *tmp = head->next;
60     //     while (nullptr != tmp) {
61     //         cout << "->" << tmp->val;
62     //         tmp = tmp->next;
63     //     }
64     //     cout << endl;
65     // }
66 public:
67     ListNode *tail = new ListNode(); //用于始终指向已排序部分的尾结点
68     ListNode *nextSubList = new ListNode(); //始终指向待排序部分的头结点
69     
70     ListNode* sortList(ListNode* head) {
71         if (!head || !head->next) return head;
72         int sz = gCount(head);
73         ListNode *start = head;
74         ListNode *dummyHead = new ListNode(0);
75         for (int size = 1; size < sz; size = size * 2) {
76             tail = dummyHead;
77             while (start) {
78                 if (!start->next) {
79                     tail->next = start;
80                     break;
81                 }
82                 ListNode *mid = split(start, size);
83                 mergeList(start, mid);
84                 start = nextSubList;
85             }
86             start = dummyHead->next;
87         }
88         return dummyHead->next;
89     }   
90 };
原文地址:https://www.cnblogs.com/qinduanyinghua/p/13664965.html