在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0 输出: -1->0->3->4->5
按照题目要求,在O(n log n)时间复杂度下,首先想到七大排序中的归并排序,因为快排的需要双指针,指向首尾,单链表后一个元素没有前一个元素指针。
思路:和归并排序思路一样,归并思想不在此叙述,下面附上归并排序链接:https://www.cnblogs.com/du001011/p/10520272.html
代码如下:
/*
1.归并排序思想
2.找到中间节点
3.进行归并排序
*/
public static ListNode sortList(ListNode head) { return head == null ? head:mergeSort(head); } //归并
private static ListNode mergeSort(ListNode head) { if (head.next == null) { return head; }
//快慢指针找出中间结点,这块需要注意一点就是
//我们需要一个标记sign跟踪慢结点,当找出中间结点时,
//让中间结点前一结点即sign的下一个结点指向空
//这样做的目的是为了使前半部分链表和后半部分链表进行合并排序
//慢结点 ListNode s = head;
//快结点 ListNode f = head;
//标记结点 ListNode sign = null; while (f.next != null) { sign = s; s = s.next; f = f.next.next; }
//标记结点下一个结点为空 sign.next = null; ListNode left = mergeSort(head); ListNode right = mergeSort(s); return merge(left, right); } //合并两个链表
public static ListNode merge(ListNode l, ListNode r) { ListNode dummyHead = new ListNode(0); ListNode cur = dummyHead; while (l != null && r != null) { if (l.val <= r.val) { cur.next = l; cur = cur.next; l = l.next; } else { cur.next = r; cur = cur.next; r = r.next; } } if (l != null) { cur.next = l; } if (r != null) { cur.next = r; } return dummyHead.next; }