题目
输入一个链表的头节点,请将该链表排序。
分析
归并排序的主要思想是将链表分成两个子链表,在对两个子链表排序后再将它们合并成一个排序的链表。
这里可以用快慢双指针的思路将链表分成两半。如果慢指针一次走一步,快指针一次走两步,当快指针走到链表尾部时,慢指针只走到链表的中央,这样也就找到了链表后半部分的头节点。
解
public class Test {
public static void main(String[] args) {
ListNode listNode1 = new ListNode(1);
ListNode listNode2 = new ListNode(2);
ListNode listNode3 = new ListNode(3);
ListNode listNode4 = new ListNode(4);
ListNode listNode5 = new ListNode(5);
ListNode listNode6 = new ListNode(6);
listNode3.next = listNode5;
listNode5.next = listNode1;
listNode1.next = listNode4;
listNode4.next = listNode2;
listNode2.next = listNode6;
ListNode result = sortList(listNode3);
while (result != null) {
System.out.println(result.val);
result = result.next;
}
}
public static ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode head1 = head;
ListNode head2 = split(head);
head1 = sortList(head1);
head2 = sortList(head2);
return merge(head1, head2);
}
private static ListNode split(ListNode head) {
ListNode slow = head;
ListNode fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode second = slow.next;
slow.next = null;
return second;
}
private static ListNode merge(ListNode head1, ListNode head2) {
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
while (head1 != null && head2 != null) {
if (head1.val < head2.val) {
cur.next = head1;
head1 = head1.next;
}
else {
cur.next = head2;
head2 = head2.next;
}
cur = cur.next;
}
cur.next = head1 == null ? head2 : head1;
return dummy.next;
}
}