原题地址:https://leetcode-cn.com/problems/sort-list/description/
题目描述:
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
解题方案:
本题对时间复杂度有要求:在 O(n log n) 时间复杂度和常数级空间复杂度下。因此平常使用的插入法和交换法都不能使用,这里就会想到归并法。归并之前,需要对链表进行对半拆分。
再提一下,归并两个链表的函数使用了一个小小的技巧,引入了头节点,这样在操作上比较容易返回链表。
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l, ListNode* r){
ListNode* head = new ListNode(-1);
ListNode* tmp = head;
if (!l) return r;
if (!r) return l;
while(l && r)
{
if(l->val > r->val)
{
tmp->next = r;
r = r->next;
}
else
{
tmp->next = l;
l = l->next;
}
tmp = tmp->next;
}
if(!l)
tmp->next = r;
else
tmp->next = l;
return head->next;
}
ListNode* sortList(ListNode* head) {
if(!head||!head->next)
return head;
ListNode* p=head;
ListNode* q=head;
//两个指针法实现从中间切分
while(q->next != NULL)
{
q = q->next->next;
if(q == NULL)
break;
p = p->next;
}
ListNode* right = p->next;
p->next = NULL;
ListNode* left = sortList(head);
right = sortList(right);
return mergeTwoLists(left, right);
}
};
后来看了其他博主的方法,发现multimap很神奇,虽然本题要求的是常数级空间复杂度。与map不同,multimap是自动根据key值进行升序排序。map的key必须独一无二,multimap的key可以重复。multimap参考资料:https://blog.csdn.net/yutianxin123/article/details/52454252
代码如下:
/**
* 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) {
multimap<int,ListNode*> mul;
while(head){
mul.insert(make_pair(head->val,head));
head=head->next;
}
ListNode* dummy(-1);
head = dummy;
for(auto it = mul.begin(); it != mul.end(); it ++){
head->next = it->second;
head = head->next;
}
head->next=NULL;
return dummy->next;
}
};