单链表的归并排序

转自
https://blog.csdn.net/u010853261/article/details/54884650

Question: 148. Sort List

Sort a linked list in O(n log n) time using constant space complexity.
中文:使用恒定的空间复杂度排序一个链表,要求时间复杂度是O(nlogn)

我们知道题目的要求是时间复杂度是O(nlogn), 很自然我们就想到了二路归并排序或则是快速排序。碎玉快速排序来说,设计到大量的精准索引定位,所以对于双链表来说更加适合,而这里是单链表,所以我选择二路归并排序。

现在我们这里需要用单链表实现,唯一的区别就是链表的分片,这里的分片我们选用的方法是双指针法,每次一个指针后移一位,另外一个后移两位。

/**
 * 合并两个有序链表
 * @param l1
 * @param l2
 * @return
 */
private static ListNode merge(ListNode l1, ListNode l2) {
    ListNode l = new ListNode(0), p = l;

    while (l1 != null && l2 != null) {
        if (l1.val < l2.val) {
            p.next = l1;
            l1 = l1.next;
        } else {
            p.next = l2;
            l2 = l2.next;
        }
        p = p.next;
    }

    if (l1 != null)
        p.next = l1;

    if (l2 != null)
        p.next = l2;

    return l.next;
}

/**
 * 链表的二路归并排序
 * @param head
 * @return
 */
public static ListNode sortList(ListNode head) {
    //空链表或则只有一个结点,直接返回head
    if(head == null || head.next==null){
        return head;
    }

    //1. 将list 切分为两个部分
    ListNode prev=null, slow=head, fast=head;

    while (fast !=null && fast.next !=null){
        prev = slow;
        slow = slow.next;//slow指针后移一个数据
        fast = fast.next.next;//fast指针后移两个数据
    }

    prev.next = null;//将链表切断

    //分别排序前后两个部分
    ListNode l1 = sortList(head);
    ListNode l2 = sortList(slow);

    return merge(l1, l2);
}

测试用例:

public static void main(String[] args) {
    ListNode head = new ListNode(0);
    ListNode n1 = new ListNode(2);
    ListNode n2 = new ListNode(4);
    ListNode n3 = new ListNode(1);
    ListNode n4 = new ListNode(3);
    head.next = n1;
    n1.next = n2;
    n2.next=n3;
    n3.next =n4;

    ListNode h =  sortList(head);

    while (h!=null){
        System.out.print(h.val + ",");
        h = h.next;
    }
}

运行结果:

0,1,2,3,4,

猜你喜欢

转载自blog.csdn.net/csdnlijingran/article/details/83781021
今日推荐