/** * Definition for singly-linked list. * function ListNode(val, next) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } */ function ListNode(val, next) { this.val = (val === undefined ? 0 : val); this.next = (next === undefined ? null : next); } /** * @param {ListNode} head * @return {ListNode} */ const sortList = function (head) { }; /* 利用归并排序的思想,将链表分成两半,分别对两半进行排序,然后合并两个已排序的链表。 */ function f1(head) { if (!head || !head.next) return head; let tail = head; while (tail.next) { tail = tail.next; } return merge(head, tail); } /* 将一个链表归并成一个有序列表,具体过程可以参考归并排序,不好描述,但不是很难 */ function merge(head, tail) { if (head === tail) return head; // 快慢指针计算中间节点 let low = head; let fast = head; while (fast.next && fast.next.next) { low = low.next; fast = fast.next.next; } const mid = low; // 将链表从中间截断 const head2 = mid.next; mid.next = null; // 将截断后的两个链表继续进行merge操作,之后将其合并成一个有序的链表返回 return mergeList(merge(head, mid), merge(head2, tail)); } /* 合并两个有序链表 */ function mergeList(l1, l2) { // 至少一个为空的情况 if (!l1 || !l2) { // 返回其中任意一个不为空的情况 return l1 || l2; } // 两个链表都不为空,将两个链表中的所有节点按大小拼接到dummy上,最后返回dummy.next const dummy = new ListNode(0); let cur = dummy; while (l1 && l2) { if (l1.val <= l2.val) { cur.next = l1; l1 = l1.next; } else { cur.next = l2; l2 = l2.next; } cur = cur.next; } // 当一个链表处理完毕,还会右一个列表存在节点,将它拼接到cur.next上 cur.next = l1 === null ? l2 : l1; return dummy.next; } /* 优化上面的写法,思路一致,但是只传入一个参数head,表示一个链表的头节点 */ function f2(head) { // 如果链表为空,或者只有一个节点,直接返回head if (head === null || head.next === null) { return head; } // 通过快慢指针寻找中间节点,将链表分成左右两部分 let slow = head; let fast = head; let prev = null; while (fast && fast.next) { prev = slow; slow = slow.next; fast = fast.next.next; } // 把链表从中间断开 prev.next = null; const left = f2(head); const right = f2(slow); return mergeList(left, right); } /* 利用快速排序的思想,将链表分成三部分,left, pivot, right,left表示小于pivot的部分,right表示大于pivot的部分,最后将它们拼接起来。 */ function quickSortList(head) { if (!head || !head.next) return head; const pivot = head; const leftDummy = new ListNode(0); const rightDummy = new ListNode(0); let leftCur = leftDummy; let rightCur = rightDummy; let cur = head.next; // 分组:< pivot 到 left,≥ pivot 到 right while (cur) { if (cur.val < pivot.val) { leftCur.next = cur; leftCur = leftCur.next; } else { rightCur.next = cur; rightCur = rightCur.next; } cur = cur.next; } // 截断,避免串联成环 leftCur.next = null; rightCur.next = null; pivot.next = null; // 断开 pivot 和旧链表的联系 const leftSorted = quickSortList(leftDummy.next); const rightSorted = quickSortList(rightDummy.next); // 拼接三段:leftSorted + pivot + rightSorted return concat(leftSorted, pivot, rightSorted); } // 拼接:将 left + pivot + right 接成一个链表并返回头结点 function concat(left, pivot, right) { let head = pivot; if (left) { head = left; let tail = left; while (tail.next) { tail = tail.next; } tail.next = pivot; } pivot.next = right; return head; }