链表排序
给定链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
输入:head = [4,2,1,3] 输出:[1,2,3,4]
因为链表不支持随机访问,所以用归并排序将其拆分成小段链表,排序后再连接起来效率最高。
该题是三个小题的组合:归并排序 + 双指针找单链表中点 + 合并两个排序链表。
可参考https://chun53.top/967.html和归并排序文章
对链表自顶向下归并排序的过程如下。
- 找到链表的中点,以中点为分界,将链表拆分成两个子链表。寻找链表的中点可以使用快慢指针的做法,快指针每次移动 2 步,慢指针每次移动 1步,当快指针到达链表末尾时,慢指针指向的链表节点即为链表的中点。
- 对两个子链表分别递归成单个结点。再合并成有序子链表。
- 将两个排序后的子链表合并,得到完整的排序后的链表。
上述过程可以通过递归实现。递归的终止条件是链表的节点个数小于或等于 1,即当链表为空或者链表只包含 1个节点时,不需要对链表进行拆分和排序。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/7WHec2/solution/lian-biao-pai-xu-by-leetcode-solution-0rjx/
来源:力扣(LeetCode)
时间复杂度:,其中 n 是链表的长度
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var sortList = function(head) {
return finmidsort(head,null)
};
function ListNode(x){
this.val = x;
this.next = null;
}
function Merge(pHead1, pHead2)//链表合并
{
// write code here
if (!pHead1) return pHead2;
if (!pHead2) return pHead1;
let cur=new ListNode(0);
let head=cur;
while(pHead1 && pHead2){
if (pHead1.val <=pHead2.val){
cur.next = pHead1;
pHead1=pHead1.next;
}
else {
cur.next = pHead2;
pHead2=pHead2.next;
}
cur=cur.next;
}
if (pHead1) cur.next = pHead1;
else cur.next = pHead2;
return head.next;
}
function finmidsort(head,tail){
if (head === null) {//判断为null或只有一个节点
return head;
}
if (head.next === tail) {//如果节点的next是tail,截去尾巴
head.next = null;
return head;
}
let slow = head, fast = head;
while (fast !== tail ) {
slow = slow.next;
fast = fast.next;
if (fast !== tail) {
fast = fast.next;
}
}
const mid = slow;//mid为新链表的头结点,故将tail设置为mid来分割2个链表
let left = finmidsort(head,mid);//递归到单个节点
let right = finmidsort(mid,tail);
return Merge(left, right);//再归并
}
阅读剩余
版权声明:
作者:chun
链接:https://chun53.top/979.html
文章版权归作者所有,未经允许请勿转载。
THE END