刷题笔记单链表的排序
Posted 傅耳耳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题笔记单链表的排序相关的知识,希望对你有一定的参考价值。
题目描述
给定一个节点数为n的无序单链表,对其按升序排序。
数据范围:
0
<
n
≤
1000000
0<n≤1000000
0<n≤1000000
要求:空间复杂度
O
(
n
)
O(n)
O(n),时间复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
示例
示例1:
输入:[1,3,2,4,5]
返回值:1,2,3,4,5
示例2:
输入:[-1,0,-2]
返回值:-2,-1,0
思路1:使用STL和sort函数
值排序
- 遍历链表,将每个结点的值存储到 v e c t o r vector vector 中
- 对 v e c t o r vector vector 进行升序排序
- 逐个插入,建立新链表
时间复杂度:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
空间复杂度:
O
(
n
)
O(n)
O(n)
ListNode* sortInList(ListNode* head)
// write code here
vector<int> v;
ListNode* newHead = new ListNode(-1);
while(head)
v.push_back(head->val);
head = head->next;
//quick_sort(v, 0, v.size()-1);
sort(v.begin(), v.end());
ListNode* r = newHead;
for(int i = 0;i < v.size();i ++ )
r->next = new ListNode(v[i]);
r = r->next;
r->next = nullptr;
return newHead->next;
【注】使用自己写的quick_sort快速排序函数,大数据运行超时
原因:STL的sort函数底层实现并非是单纯的快排,有排序算法的优化。
详见STL sort算法的实现
思路2:归并排序
真正对链表排序,归并排序,分治思想
-
快慢指针找链表中点
fast 每次走两步,slow每次走一步 fast走到链表结尾,slow到达链表中点
-
从中点将链表分为左右两部分链表
left -> [head, slow] right -> [slow->next, nullptr)
-
递归对两部分链表排序
-
合并两个有序链表
时间复杂度:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
空间复杂度:
O
(
1
)
O(1)
O(1)
ListNode* sortInList(ListNode* head)
// write code here
//递归出口 为空或者只有一个元素时不需要排序
if(!head || !head->next)
return head;
//1. 快慢指针找中点
ListNode* fast = head->next;
ListNode* slow = head;
while(fast && fast->next)
fast = fast->next->next;
slow = slow->next;
//找中点
//(1 2 3 4 5)slow = 3 奇数 中心点
//(1 2 3 4) slow = 2 偶数 中心左边点
//2. 分隔链表
ListNode* temp = slow->next;
slow->next = nullptr;
//3. 递归排序两部分
ListNode* left = sortInList(head);
ListNode* right = sortInList(temp);
//4. 合并两部分
ListNode* newHead = new ListNode(-1);
ListNode* r = newHead;
while(left && right)
if(left->val < right->val)
r->next = left;
left = left->next;
else
r->next = right;
right = right->next;
r = r->next;
r->next = left ? left : right;
return newHead->next;
以上是关于刷题笔记单链表的排序的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode Java刷题笔记—109. 有序链表转换二叉搜索树
LeetCode Java刷题笔记—83. 删除排序链表中的重复元素