题目描述:
Sort a linked list in O(n log n) time using constant space complexity
归并排序的一般步骤为:
1)将待排序数组(链表)取中点并一分为二;
2)递归地对左半部分进行归并排序;
3)递归地对右半部分进行归并排序;
4)将两个半部分进行合并(merge),得到结果。
所以对应此题目,可以划分为三个小问题:
1)找到链表中点 (快慢指针思路,快指针一次走两步,慢指针一次走一步,快指针在链表末尾时,慢指针恰好在链表中点);
2)写出merge函数,合并两个有序链表。
3)写出mergesort函数,实现上述步骤。
package suda.alex.leetcode;
public class SortList {
public ListNode sortList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode middleNode = findMiddleNode(head);
ListNode rightLNode = sortList(middleNode.next);//后半部分排序
middleNode.next = null; //截断后半部分
ListNode leftLNode = sortList(head);//前半部分排序
return mergeTwoSortedLNode(leftLNode, rightLNode);
}
public static ListNode findMiddleNode(ListNode head) {
ListNode slow = head;
ListNode fast = head.next;
while(fast!=null && fast.next!=null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public static ListNode mergeTwoSortedLNode(ListNode head1, ListNode head2) {
if(head1 == null){
return head2;
}
if(head2 == null){
return head1;
}
ListNode sortedDummyList = new ListNode(0);
ListNode head = sortedDummyList;
while(head1 != null && head2 != null){
if(head1.val > head2.val){
head.next = head2;
head2 = head2.next;
}
else{
head.next = head1;
head1 = head1.next;
}
head = head.next;
}
if(head1 == null){
head.next = head2;
}
if(head2 == null){
head.next = head1;
}
return sortedDummyList.next;
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}