单链表的归并排序

来源:互联网 发布:php免费开源微信平台 编辑:程序博客网 时间:2024/05/20 13:04

本题目来源于LeetCode,具体如下:

Sort a linked list in O(n log n) time using constant space complexity.

题目要求复杂度O(nlogn),因此我们很自然考虑使用快速排序或者归并排序,但是后来经过实践证明,使用快速排序总是AC超时,归并排序则可以正确AC。

分析一下原因,个人认为是与测试数据有关,因为快速排序不能保证算法复杂度一定是O(nlogn),当数据比较集中时,即使做随机选取key值,算法的复杂度也非常接近O(N^2),因此会出现超时,所以考虑使用归并排序。

下面是采用归并排序的思路已经AC代码:

主要考察3个知识点,
知识点1:归并排序的整体思想
知识点2:找到一个链表的中间节点的方法
知识点3:合并两个已排好序的链表为一个新的有序链表

归并排序的基本思想是:找到链表的middle节点,然后递归对前半部分和后半部分分别进行归并排序,最后对两个以排好序的链表进行Merge。

public class CzyList {/** * Definition for singly-linked list. * public class ListNode { *     int val; *     ListNode next; *     ListNode(int x) { val = x; } * } */    public static ListNode sortList(ListNode head) {        if (head == null || head.next == null)            return head;        ListNode f = head.next.next;        ListNode p = head;        while (f != null && f.next != null) {            p = p.next;            f =  f.next.next;        }                ListNode temp=p.next;        p.next=null;        ListNode h1=sortList(head);        //p.next=null;        ListNode h2 = sortList(temp);        //p.next = null;//保证每次分半之后  前半都有一个结尾标志null;;;;;;                return merge(h1, h2);    }    public static ListNode merge(ListNode h1, ListNode h2) {        ListNode hn = new ListNode(Integer.MIN_VALUE);        ListNode c = hn;        while (h1 != null && h2 != null) {            if (h1.val < h2.val) {                c.next = h1;                h1 = h1.next;            }            else {                c.next = h2;                h2 = h2.next;            }            c = c.next;        }        if (h1 != null)            c.next = h1;        if (h2 != null)            c.next = h2;        return hn.next;    }public static void main(String[] args){ListNode head=new ListNode(6);head.next=new ListNode(3);head.next.next=new ListNode(5);head.next.next.next=new ListNode(4);head=sortList(head);while(head!=null){System.out.println(head.val);head=head.next;}}}


0 0