Leetcode-Sort List(Java)

Question:

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

Thinking:

There are three basic algorithm to sort in n*logn time. They are merge sort, heap sort and quick sort. And I implement the sort method in merge sort. In order to do this, I have to implement the function such as getLength, get the mid node, merge and so on.

Basic idea of merge sort is to divide a list into two lists, and make them sorted then merge them together.

Solution:

//merge
public ListNode sortList(ListNode head) {
    int len = getLength(head);
    if (len == 0)    return null;
    ListNode nhead = mergeSort(head, len);
    addTail(nhead, len);
    return nhead;
}

private ListNode mergeSort(ListNode head, int n) {
    if (n <= 1)
        return head;
    ListNode mid = getNode(head, n/2);
    ListNode nhead = mergeSort(head, n/2);
    ListNode nmid = mergeSort(mid, n - n/2);
    return merge(nhead, nmid, n);
}

private int getLength(ListNode head) {
    int l = 0;

    while (head != null) {
        head = head.next;
        l++;
    }

    return l;
}

private ListNode getNode(ListNode head, int index) {
    while (index > 0) {
        head = head.next;
        index--;
    }

    return head;
}

private ListNode merge(ListNode p1, ListNode p2, int len) {
    ListNode dummy = new ListNode(0);
    ListNode p = dummy;
    int l1 = 0;
    int l2 = 0;
    while (l1 < len/2 && l2 < len - len/2) {
        if (p1.val < p2.val) {
            p.next = p1;
            p1 = p1.next;
            p = p.next;
            l1++;
        } else {
            p.next = p2;
            p2 = p2.next;
            p = p.next;
            l2++;
        }
    }
    if (l1 == len/2) {
        p.next = p2;
    } else {
        p.next = p1;
    }
    return dummy.next;
}

private void addTail(ListNode head, int n) {
    while (n > 1) {
        head = head.next;
        n--;
    }
    head.next = null;
}

More efficient method:
Reference:https://leetcode.com/discuss/1709/have-pretty-mergesort-method-anyone-speed-reduce-memory-usage

It use the fast pointer and slow pointer to find the middle index of the linked list. Add a null to the first half to implement the merge operation.

public 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 h2 = sortList(p.next);
    p.next = null;
    return merge(sortList(head), h2);
}
public 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;
}