sort list: https://leetcode.com/problems/sort-list/
数组的排序比较相对于链表的,还是比较容易的。链表的排序,有一个最麻烦的地方就是,无法通过下标来访问节点,所以操作起来就没有数组那么方便。
链表排序,拿到这题,第一个想到的是快排。快排的思路和数组的一模一样,只不过要多两个list指针,一个指向比较节点的left, 一个指向比较节点的right。从左往右遍历整个链表就可以了,快排过一次的链表,比较节点的位置都是正确地,然后用递归,排左边和右边,虽然有点麻烦,但还可以,思路比较简单。
class Solution {
public:
ListNode* sortList(ListNode* head) {
return sort(head, 0);
}
ListNode* sort(ListNode* head, ListNode* end)
{ if(head == end)
return head;
ListNode* saveHead = head;
ListNode* preHead = NULL;
ListNode* lList = head;
ListNode* rList = head;
head=head->next;
while(head!= end ){
if(head->val > saveHead->val){
rList->next = head;
rList = rList->next;
head = head->next;
}
else{
ListNode* temphead = head->next;
head->next = lList;
lList= head;
head = temphead;
if(!preHead)
preHead = lList;
}
}
rList->next =end;
if(preHead != NULL)
{
preHead->next = saveHead;
lList = sort(lList, saveHead);
}
saveHead->next = sort(saveHead->next, end);
return lList;
}
};
这个结果,Time Limit Exceeded。
简直了,用的例子是节点的数字只有1,2,3,然后有几百个节点。快排的弊端,最坏情况下o(n2)的时间复杂度,马上体现出来了……
没办法,只有用归并排序了。归并的话最坏都是O(nlogn)的。
归并的话主要思路:首先,要把整个List,分成两个List,然后各自排序,在进行归并算法。两个子List,排序也是用归并,这里面的采用递归的方法。对子链表一直归并,知道子链表无法再分成两个链表为止。和数组的归并算法是一样的,只是数组的归并算法采用下表的方法来吧数组分成两个小数组,而链表,是真正把整个链表分开的。
这里主要用到两个子函数,split是把链表分成两个子链表,而merge是把两个有序链表进行归并排序。
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head==0 || head->next==0)
return head;
ListNode* mid = split(head);
return merge(sortList(head), sortList(mid));
}
ListNode* merge(ListNode* start1, ListNode* start2)
{
ListNode* head = 0;
if(start2 == 0)
return start1;
if(start1->val < start2->val)
{
head = start1;
start1 = start1->next;
}
else {
head = start2;
start2 = start2->next;
}
ListNode* tempList = head;
while(start1!= 0 && start2 != 0){
if(start1->val > start2->val){
tempList->next = start2;
start2 = start2->next;
tempList = tempList->next;
}
else{
tempList->next = start1;
start1 = start1->next;
tempList = tempList->next;
}
}
if(start1 == 0)
tempList->next = start2;
else
tempList->next = start1;
return head;
}
ListNode* split(ListNode* head){
ListNode* fast = head;
ListNode* slow = head;
while(fast!= 0 && fast->next != 0 && fast->next->next !=0)
{
fast = fast->next->next;
slow = slow->next;
}
ListNode* midList = slow->next;
slow->next =0;
return midList;
}
};