1.题目
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
排序链表
2.思路
方法一:自顶向下归并排序
对链表自顶向下归并排序的过程如下。
找到链表的中点,以中点为分界,将链表拆分成两个子链表。寻找链表的中点可以使用快慢指针的做法,快指针每次移动 2 步,慢指针每次移动 1 步,当快指针到达链表末尾时,慢指针指向的链表节点即为链表的中点。
对两个子链表分别排序。
将两个排序后的子链表合并,得到完整的排序后的链表。可以使用「21. 合并两个有序链表」的做法,将两个有序的子链表进行合并。
上述过程可以通过递归实现。递归的终止条件是链表的节点个数小于或等于 1,即当链表为空或者链表只包含 1个节点时,不需要对链表进行拆分和排序。
3.代码
public ListNode sortList() {
return sortList(head, null);
}
public ListNode sortList(ListNode head, ListNode tail) {
if (head == null) {
return head;
}
if (head.next == tail) {
head.next = null;
return head;
}
ListNode fast = head;
ListNode slow = head;
while (fast != tail && fast.next != tail) {
fast = fast.next.next;
slow = slow.next;
}
ListNode mid = slow;
ListNode node1 = sortList(head, mid);
ListNode node2 = sortList(mid, tail);
ListNode node = merge(node1, node2);
return node;
}
public ListNode merge(ListNode l1, ListNode l2) {
ListNode newHead = new ListNode(-1);
ListNode tmp = newHead;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
tmp.next = l1;
l1 = l1.next;
} else {
tmp.next = l2;
l2 = l2.next;
}
tmp = tmp.next;
}
if (l1 != null) {
tmp.next = l1;
} else if (l2 != null) {
tmp.next = l2;
}
return newHead.next;
}
测试:
public static void main(String[] args) {
LinkedList list=new LinkedList();
list.addLast(1);
list.addLast(3);
list.addLast(5);
list.addLast(2);
list.addLast(0);
System.out.print("排序前:");
list.display();
System.out.println("++++++++++++++");
System.out.print("排序后:");
ListNode ret=list.sortList();
list.display(ret);
}