好题目,总结一下。
要求时间效率O(NlogN),空间限制为O(1)
1、暴力显然不行,于是想到那几种排序,堆排,快排,归并。堆排空间O(N),pass;快排,给出的ListNode结构没有parent指针,pass;
2、归并,觉得也是空间O(N),绝望。后来看了看别人的解法,顿觉自己还是too naive。既然已经是链表了,merge的时候把对位的连到后边不就行,怎么会蠢到想去一个个复制那些节点。
3、由于是链表,没有下标,计算mid位置的时候有一个小trick:快慢指针。快指针一次走两步,慢指针一次走一步。快指针走到链表末尾的时候,慢指针正好走到mid位置。(如果要求走到1/4位置呢?快4慢1)。
#include <iostream>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *sortList(ListNode *head)
{
if(!head || !head->next)
return head;
ListNode *slow = head, *quick = head;
ListNode *pre = slow;
while(quick)
{
if(quick->next)
{
pre = slow;
slow = slow->next;
quick = quick->next;
if(quick->next)
quick = quick->next;
else
break;
}
else
break;
}
pre->next = 0;
ListNode *l = sortList(head);
ListNode *r = sortList(slow);
return merge(l, r);
}
ListNode* merge(ListNode *l, ListNode *r)
{
ListNode *head = new ListNode(0);
ListNode *p = head;
while(l && r)
{
if(l->val < r->val)
{
p->next = l;
l = l->next;
}
else
{
p->next = r;
r = r->next;
}
p = p->next;
}
if(l)
p->next = l;
else
p->next = r;
p = head->next;
head->next = 0;
delete head;
return p;
}
void insert(ListNode *head, int val)
{
ListNode *p = new ListNode(val);
if(!head)
return;
else
{
while(head->next)
{
head = head->next;
}
head->next = p;
}
}
void print(ListNode *head)
{
while(head->next)
{
head = head->next;
cout << head->val << " ";
}
cout << endl;
}
};
int main(void)
{
Solution s;
ListNode head(0);
for(int i = 9; i > 0; --i)
s.insert(&head, i);
s.print(&head);
s.sortList(&head);
s.print(&head);
return 0;
}