Link: https://leetcode.com/problems/reorder-list/

Idea

  1. Find the middle point of the list and divide the list into two parts by setting mid.next = null;
  2. reverse the second half
  3. Merge two list by retrieving one node from each list at a time

Code

public class Solution {
    public void reorderList(ListNode head) {
        if (head == null || head.next == null) {
            return;
        }
        
        ListNode mid = findMid(head);
        ListNode p1 = head;
        ListNode p2 = reverse(mid.next);
        mid.next = null;
        
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
        while (p1 != null && p2 != null) {
            tail.next = p1;
            p1 = p1.next;
            tail = tail.next;
            
            tail.next = p2;
            p2 = p2.next;
            tail = tail.next;
        }
        
        if (p1 != null) {
            tail.next = p1;
        }
        
        head = dummy.next;
    }
    
    private ListNode findMid(ListNode head) {
        if (head == null) {
            return null;
        }
        
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        
        return slow;
    }
    
    private ListNode reverse(ListNode head) {
        if (head.next == null) {
            return head;
        }
        
        ListNode newHead = reverse(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
}