给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

    进阶:你可以在排序列表 - 图1时间复杂度和常数级空间复杂度下,对链表进行排序吗?

    示例 1
    排序列表 - 图2

    1. 输入:head = [4,2,1,3]
    2. 输出:[1,2,3,4]

    示例 2:
    排序列表 - 图3

    1. 输入:head = [-1,5,3,4,0]
    2. 输出:[-1,0,3,4,5]

    示例 3:

    1. 输入:head = []
    2. 输出:[]

    提示:

    • 链表中节点的数目在范围 [0, 5 * 104] 内
    • -105 <= Node.val <= 105

    如果不考虑时空复杂度,最简单直接的方式便是:

    • 遍历链表获取所有节点的值
    • 将所有节点值进行升序排列
    • 利用排序后的结果重构新的链表

    此时,时间复杂度为排序列表 - 图4,空间复杂度为排序列表 - 图5,其中排序列表 - 图6为链表的长度。

    解题代码如下:

    1. /**
    2. * Definition for singly-linked list.
    3. * public class ListNode {
    4. * int val;
    5. * ListNode next;
    6. * ListNode() {}
    7. * ListNode(int val) { this.val = val; }
    8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    9. * }
    10. */
    11. class Solution {
    12. public ListNode sortList(ListNode head) {
    13. if(head == null || head.next == null)
    14. return head;
    15. List<Integer> list = new ArrayList<>();
    16. ListNode cur = head;
    17. while(cur != null){
    18. list.add(cur.val);
    19. cur = cur.next;
    20. }
    21. list.sort((o1, o2) -> o1-o2);
    22. ListNode dummy = new ListNode();
    23. cur = dummy;
    24. for(Integer e : list){
    25. cur.next = new ListNode(e);
    26. cur = cur.next;
    27. }
    28. return dummy.next;
    29. }
    30. }

    如果要求在排序列表 - 图7的时间复杂度内完成链表的排序,那么上述的方法显然就无法满足了。而常用的满足排序列表 - 图8时间复杂度要求的排序算法有快速排序、堆排序和归并排序,该题可以采用归并排序的思想来降低时间复杂度。

    采用归并排序来解决链表升序排列的整体思路如下:

    • 采用快慢指针来寻找链表中点
    • 将中点左右的两个有序子链表合并
    • 设置好递归出口,即:
      • 排序列表 - 图9,表示链表为空
      • 或者排序列表 - 图10,表示只包含一个节点

    有序链表合并的过程就是不断的遍历两个链表,选择当前的最小的的节点作为结果链表的排序列表 - 图11,直到两个链表中的节点全部遍历完毕。

    解题代码如下:

    1. /**
    2. * Definition for singly-linked list.
    3. * public class ListNode {
    4. * int val;
    5. * ListNode next;
    6. * ListNode() {}
    7. * ListNode(int val) { this.val = val; }
    8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    9. * }
    10. */
    11. class Solution {
    12. public ListNode sortList(ListNode head) {
    13. if(head == null || head.next == null)
    14. return head;
    15. return sortList(head, null);
    16. }
    17. public ListNode sortList(ListNode head, ListNode tail){
    18. // 递归出口
    19. if(head == null)
    20. return head;
    21. if(head.next == tail){
    22. head.next = null;
    23. return head;
    24. }
    25. // 平均断开链表
    26. // 快慢指针寻找中点
    27. ListNode slow = head;
    28. ListNode fast = head;
    29. while (fast != tail) {
    30. slow = slow.next;
    31. fast = fast.next;
    32. if (fast != tail) {
    33. fast = fast.next;
    34. }
    35. }
    36. ListNode left = sortList(head, slow);
    37. ListNode right = sortList(slow, tail);
    38. ListNode mer = mergeList(left, right);
    39. return mer;
    40. }
    41. public ListNode mergeList(ListNode left, ListNode right){
    42. ListNode dummy = new ListNode();
    43. ListNode cur = dummy;
    44. while(left != null && right != null){
    45. if(left.val <= right.val){
    46. cur.next = left;
    47. left = left.next;
    48. } else {
    49. cur.next = right;
    50. right = right.next;
    51. }
    52. cur = cur.next;
    53. }
    54. if(left != null){
    55. cur.next = left;
    56. } else if(right != null){
    57. cur.next = right;
    58. }
    59. return dummy.next;
    60. }
    61. }