在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
思路1:暴力解决,拿出来,再放回去
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
vector<int> temp;
ListNode* h = head;
while(h!=NULL){
temp.push_back(h->val);
h = h->next;
}
sort(temp.begin(),temp.end());
ListNode* r = head;
int i=0;
while(r!=NULL){
r->val = temp[i++];
r = r->next;
}
return head;
}
};
思路2:复杂度要求为nlog2n,能想到的就是快排,堆排,归并排序。快排要找到第n个数由于是链表只能顺序找,太慢了,所以pass;堆排的空间复杂度为O(n),pass,只剩下堆排了,利用快慢指针找到中间节点进行分段,合并利用合并两个有序链表的方法,前面有这道题,然后就是递归了。
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head == NULL || head->next == NULL) //递归出口
return head;
ListNode* head1 = head;
ListNode* head2 = getMiddle(head);
head1 = sortList(head1); //对前半段进行递归
head2 = sortList(head2); //对后半段进行递归
return merge(head1, head2);
}
//归并
ListNode* merge(ListNode* head1, ListNode* head2){
ListNode* dummyHead = new ListNode(-1);
ListNode* cur = dummyHead;
while(head1 != NULL && head2 != NULL){
if(head1->val > head2->val){
cur->next = head2;
head2 = head2->next;
}
else{
cur->next = head1;
head1 = head1->next;
}
cur = cur->next;
}
if(head1 == NULL)
cur->next = head2;
if(head2 == NULL)
cur->next = head1;
return dummyHead->next;
}
//获取链表中间位置,并将链表从中间分为两个链表
ListNode* getMiddle(ListNode* head){
//使用快慢节点方法寻找链表的中间节点
ListNode *fast = head, *slow = head;
while(fast->next != NULL && fast->next->next != NULL){
slow = slow->next;
fast = fast->next->next;
}
fast = slow;
slow = slow->next; //第二个链表的首节点
fast->next = NULL; //将原来的链表从中间断开
return slow;
}
};