1. 题目描述

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

示例 1:

  1. 输入: 4->2->1->3
  2. 输出: 1->2->3->4

示例 2:

  1. 输入: -1->5->3->4->0
  2. 输出: -1->0->3->4->5

2. 解题思路

(1)归并排序:
题目要求在O(n log n) 时间复杂度和常数级空间复杂度下对链表进行排序,恰好归并排序可以满足要求。

其主要思路如下:

  • 先判断链表是否只有一个元素,若是则直接返回
  • 使用快慢指针,找到链表的中间节点
  • 对链表的前半部分和后半部分分别递归的进行归并排序
  • 最后将两个子链表进行合并

(2)借助数组来实现:
我们可以借助数组来实现这个题目,将链表转化为数组,对数组的元素进行排序。排序完成之后,将数组再转化为链表。
不过这种方法空间复杂度为O(n)

3. 代码实现

归并排序:

  1. /**
  2. * Definition for singly-linked list.
  3. * function ListNode(val) {
  4. * this.val = val;
  5. * this.next = null;
  6. * }
  7. */
  8. /**
  9. * @param {ListNode} head
  10. * @return {ListNode}
  11. */
  12. var sortList = function(head) {
  13. // 若为空链表或只有一个节点,就直接返回
  14. if(head === null || head.next === null){
  15. return head
  16. }
  17. // 使用快慢指针获取链表的中间值
  18. let fast = head
  19. let slow = head
  20. while(slow.next && fast.next && fast.next.next){
  21. slow = slow.next
  22. fast = fast.next.next
  23. }
  24. // 将链表分成两个
  25. const middle = slow.next
  26. slow.next = null
  27. // 对左右的两个链表分别递归的进行归并排序
  28. const left = head
  29. const right = middle
  30. return merge(sortList(left), sortList(right))
  31. };
  32. function merge (left, right) {
  33. // 初始化一个空的结果节点
  34. let res = new ListNode(null);
  35. // 当前节点
  36. let prev = res;
  37. while (left && right) {
  38. // 如果左边的值小于右边的值,当前节点指向左节点,左节点指向下一个节点
  39. if (left.val < right.val) {
  40. [prev.next, left] = [left, left.next]
  41. }else {
  42. // 如果右边的值小于左边的值,当前节点指向右节点,右节点指向下一个节点
  43. [prev.next, right] = [right, right.next];
  44. }
  45. // 当前节点指向下一个节点
  46. prev = prev.next;
  47. }
  48. // 如果还有剩余的节点,就直接拼接在结果链表的最后
  49. prev.next = left ? left : right;
  50. return res.next;
  51. }

数组实现:

  1. /**
  2. * Definition for singly-linked list.
  3. * function ListNode(val) {
  4. * this.val = val;
  5. * this.next = null;
  6. * }
  7. */
  8. /**
  9. * @param {ListNode} head
  10. * @return {ListNode}
  11. */
  12. var sortList = function(head) {
  13. if(head === null || head.next === null){
  14. return head
  15. }
  16. let cur = head
  17. let index = 0
  18. const arr = []
  19. // 将链表转化为数组
  20. while(cur){
  21. arr[index] = cur.val
  22. cur = cur.next
  23. index ++
  24. }
  25. // 对数组进行排序
  26. arr.sort((a,b) => a-b)
  27. // 将数组转化为链表
  28. cur = head
  29. index = 0
  30. while(cur){
  31. cur.val = arr[index]
  32. index ++
  33. cur = cur.next
  34. }
  35. return head
  36. };

4. 提交结果

归并排序:
148. 链表排序 - 图1
数组实现:
148. 链表排序 - 图2