https://leetcode.com/problems/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->4Example 2:
Input: -1->5->3->4->0 Output: -1->0->3->4->5
列表排序,还要求nlogn的复杂度,自然想到使用归并排序。
借鉴了别人代码中的“断尾重接”思想,获得了很大的启发
迭代版:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
int len = 0;
for(ListNode *cur = head; cur != NULL; cur = cur->next){
++len;
}
//构造头结点
ListNode *head_node = new ListNode(0);
head_node->next = head;
for(int interval = 1; interval < len; interval *= 2){
ListNode *cur_head = head_node;
ListNode *first, *second;
do{
first = cur_head;
second = cur_head;
for(int i = 0; i < interval; ++i){
if(first != NULL){
first = first->next;
second = second->next;
}else{
break;
}
}
if(first == NULL || first->next == NULL) break; //当前尾部已经落入有序区间
for(int i = 0; i < interval; ++i){
if(second != NULL){
second = second->next;
}else{
break;
}
}
ListNode *next_head = (second == NULL) ? NULL : second->next; //记录下一个归并区间头指针
//断尾+将first、second定位到头部
if(second != NULL) second->next = NULL;
second = first->next;
first->next = NULL;
first = cur_head->next;
//归并
while(first != NULL && second != NULL){
if(first->val < second->val){
cur_head->next = first;
first = first->next;
cur_head = cur_head->next;
}else{
cur_head->next = second;
second = second->next;
cur_head = cur_head->next;
}
}
if(first != NULL) cur_head->next = first;
else cur_head->next = second;
//重连
while(cur_head->next != NULL){
cur_head = cur_head->next;
}
cur_head->next = next_head;
}while(cur_head->next != NULL); //没有后继区间
}
return head_node->next;
}
};
递归版:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head == NULL || head->next == NULL) return head;
ListNode *first = head, *second = head;
// while(second != NULL && second->next != NULL){
//这个条件是不行的,因为要确保每一次递归问题规模都要缩小
//根据后面的代码逻辑,等价于确保first->next != NULL
//如果使用上述条件,在两个元素的区间下将进入死循环
//下一行的条件确保了second指针必然不为空,也就确保了first指针之后必然还有元素
while(second->next != NULL && second->next->next != NULL){
// cout << second->val << '\t';
second = second->next->next;
first = first->next;
}
// cout << endl;
second = first->next;
first->next = NULL;
ListNode *L1 = sortList(head);
ListNode *L2 = sortList(second);
return merge_list(L1, L2);
}
ListNode* merge_list(ListNode *l1, ListNode *l2){
ListNode *head = new ListNode(0);
ListNode *cur = head;
while(l1 != NULL && l2 != NULL){
if(l1->val < l2->val){
cur->next = l1;
l1 = l1->next;
cur = cur->next;
}else{
cur->next = l2;
l2 = l2->next;
cur = cur->next;
}
}
cur->next = (l1 == NULL) ? l2 : l1;
return head->next;
}
};