题目:
Sort a linked list in O(n log n) time using constant space complexity.
解题思路:
这是一个单链表的排序问题 ;
内部要求的时间复杂度为 O(N*logN) ;空间复杂度为常数,也就是说不能新建结点的。
按照我们之前学的排序算法来看的话。
时间复杂度为O(N* logN)的算法都有:堆排序 、归并排序、快速排序(近似的)
在这里,堆排肯定是用不到了,因为堆排序是要使用的是下标的。 因此排除。
归并排序到时可以试试看:
当然、快速排序也是可以的,大家不要以为快排只有那么一种方式,在快排中有一种 前后指针法,就可以解决这个问题。
代码归并排序:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
//[left,right)
//得到两个结点区间的中间节点 区间为【)
ListNode* GetMidNode(ListNode* left,ListNode* right)
{
//块慢指针法,一个走一步一个走两步
ListNode* fast = left;
ListNode* cur= left;
while(fast != right&&fast->next!= right)
{
cur = cur->next;
fast = fast->next;
if(fast != right)
fast= fast->next;
}
return cur;
}
//【)
//归并排序
//返回值为生成的有序的链表头结点
ListNode* _MergeSort(ListNode* start,ListNode* end)
{
//表示的只有一个结点
if(start->next == end)
{
//将连接断开
start->next = NULL;
return start;
}
//递归实现
ListNode* mid = GetMidNode(start,end);
ListNode* left = _MergeSort(start,mid);
ListNode* right= _MergeSort(mid,end);
//此时left 、right 表示的就是两个 有序的链表
ListNode* ret = NULL;
ListNode* tail = NULL;
while(left&&right)
{
if(left->val <= right->val)
{
if(tail)
{
tail->next = left;
tail = left;
}
else
{
ret = left;
tail = left;
}
left = left->next;
}
else
{
if(tail)
{
tail->next = right;
tail = right;
}
else
{
ret = right;
tail = right;
}
right = right->next;
}
}
while(left)
{
if(tail)
{
tail->next = left;
tail = left;
}
else
{
ret = left;
tail = left;
}
left = left->next;
}
while(right)
{
if(tail)
{
tail->next = right;
tail = right;
}
else
{
ret = right;
tail = right;
}
right = right->next;
}
return ret;
}
ListNode *sortList(ListNode *head)
{
if(head== NULL)
return NULL;
if(head->next == NULL)
return head;
return _MergeSort(head,NULL);
}
};
代码快速排序(这段代码只实用于链表结点多的时候):
//用常数空间复杂度对O(n log n)时的链表排序。
//使用快速排序
//前后指针法
//【left,right】
void _sortList(ListNode* left,ListNode* right)
{
if(left == right)
return ;
int data = right->val;
ListNode * cur = left;
ListNode * prev = NULL;
while(cur != right)
{
if(cur->val <= data)
{
if(prev == NULL)
{
prev = left;
}
else
{
prev = prev->next;
}
swap(cur->val,prev->val);
cur = cur->next;
}
else
{
cur = cur->next;
}
}
_sortList(left,prev);
if(prev == NULL)
{
prev = left;
}
else
{
prev = prev->next;
}
swap(cur->val,prev->val);
if(prev != right)
{
_sortList(prev->next,right) ;
}
}
ListNode *sortList(ListNode *head)
{
if(head == NULL)
return NULL;
if(head->next == NULL)
return head;
ListNode* node = head;
while(node->next)
{
node = node->next;
}
_sortList(head,node);
return head;
}