您的位置:首页 > 其它

LeetCode题目4:Sort List

2014-07-17 16:07 369 查看
这个题目要求在时间复杂度O(nLogn)、空间复杂度O(1)内,对单链表进行排序。常见的满足这两项要求的排序算法就是归并排序和快排。我先尝试了快排,由于在单链表中实现随机选择哨兵项A[r]不够方便,我令每组最后一个数据项为A[r](参考算法导论实现),这样做对于一般的数据应该没有问题,但对于特殊设计的数据(如本题的输入数据),还是会把快排降为O(N^2)。关于快排单链表的实现见这篇Blog利用快速排序对单链表进行排序

于是我又尝试了归并排序,这回很顺利就AC了。对链表进行归并,我习惯于分别将他们加上头指针,再进行merge合并。在合并操作时要务必小心,不要把链表指乱,事实证明我写过几次链表合并,每次写的时候还是要想一想,估计写十次以上才能默出吧。对于分裂链表(即寻找中间结点),有个小技巧:用两个指针,都从头部开始,分别以步长1,步长2对链表进行遍历,当第二个指针到达链表尾部,第一个指针就是链表中间。这里我为了令指针1的next节点是我想要的中间位置,所以初始化令指针2指向指针1的Next。最后令mid=指针1->next,指针1->next=NULL来实现对链表的割裂。

下面是代码,main函数和ListNode数据结构与Blog 利用快速排序对单链表进行排序共享,这里就省略了。

class Solution {
public:
ListNode *sortList(ListNode *head) {
if (head == NULL)
return head;
return mergeSort(head);
}
ListNode* merge(ListNode* l1, ListNode* l2)
{

ListNode* head1 = new ListNode(0);
head1->next = l1;
ListNode* node1 = head1;
ListNode* head2 = new ListNode(0);
head2->next = l2;
ListNode* node2 = head2;

while (node1->next != NULL&&node2->next != NULL)
{
if (node1->next->val <= node2->next->val)
{
node1 = node1->next;
}
else{
ListNode* tmp = node1->next;
node1->next = node2->next;
node2->next = node2->next->next;
node1->next->next = tmp;
}
}
if (node2->next != NULL)
{
node1->next = node2->next;
}
return head1->next;

}
ListNode* mergeSort(ListNode* list)
{
ListNode* p1 = list;
ListNode* p2 = list->next;
if (p2 == NULL)
return list;
if (p2->next == NULL)
{
if (p1->val > p2->val)
swap(p1->val, p2->val);
return p1;
}
while (p1->next != NULL&&p2->next != NULL)
{
p1 = p1->next;
p2 = p2->next;
if (p2 != NULL)
p2 = p2->next;
if (p2 == NULL)
break;
}
ListNode* mid = p1;
ListNode* head1 = list;
ListNode* head2 = p1->next;
p1->next = NULL;

head1 = mergeSort(head1);
head2 = mergeSort(head2);
ListNode*res=merge(head1, head2);
return res;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息