二、快速排序
使用快排也可以解决。但是注意,要加一个优化才可以过大数据,就是判断一下是不是整个链条是相同的节点,比如2 2 2 2 2 2 2 ,这样的就直接扫一次不用执行 快排,否则它会是N平方的复杂度。
快速排序1
快速排序的主要思想是:
1)选定一个基准元素
2)经过一趟排序,将所有元素分成两部分
3)分别对两部分重复上述操作,直到所有元素都已排序成功
因为单链表只能从链表头节点向后遍历,没有prev指针,因此必须选择头节点作为基准元素。这样第二步操作的时间复杂度就为O(n)。由于之后都是分别对两部分完成上述操作,因此会将链表划分为lgn个段,因此时间复杂度为O(nlgn)
快速排序的主要思想是:
1)选定一个基准元素
2)经过一趟排序,将所有元素分成两部分
3)分别对两部分重复上述操作,直到所有元素都已排序成功
因为单链表只能从链表头节点向后遍历,没有prev指针,因此必须选择头节点作为基准元素。这样第二步操作的时间复杂度就为O(n)。由于之后都是分别对两部分完成上述操作,因此会将链表划分为lgn个段,因此时间复杂度为O(nlgn)
示意图如下
代码如下(记住这个算法)
class Solution {
public:
/*
* @param head: The head of linked list.
* @return: You should return the head of the sorted linked list, using constant space complexity.
*/
ListNode * sortList(ListNode * head) {
// write your code here
if(head==NULL||head->next==NULL) return head;
quick_sort(head,NULL);
return head;
}
void quick_sort(ListNode *pBegin,ListNode *pEnd){
if(pBegin==pEnd) return;//return 到被调用的地方quick_sort(head,NULL);
ListNode *mid=partion(pBegin,pEnd);
quick_sort(pBegin,mid);
quick_sort(mid->next,pEnd);
}
ListNode *partion(ListNode *pBegin,ListNode *pEnd){
if(pBegin==pEnd||pBegin->next==pEnd) return pBegin;
int key=pBegin->val; //选择pBegin作为基准元素
ListNode *p=pBegin,*q=pBegin;
while(q!=pEnd){ //从pBegin开始向后进行一次遍历
if(q->val<key){
p=p->next;
swap(&p->val,&q->val);
}
q=q->next;
}
swap(&p->val,&pBegin->val);
return p;
}
void swap(int *a,int *b){
int t=*a;
*a=*b;
*b=t;
}
};