Site Search:

ReorderLinkedList.java



/*
 * Problem:
Given a linked list 0 -> 1 -> 2 -> 3 -> ... -> n-2 -> n-1 -> n, 
reorder the linked list as 0 -> n -> 1 -> n-1 -> 2 -> n-2 -> ...

Solution:
use fast-slow pointer to traversal the linked list.
when fast pointer find tail, the slow pointer is pointing to the middle point.
break the linked list to 2 sub-linked list at middle point.
reverse the second half
remove the node from second half
start from the head of first half, insert element behind each node
 */
public class ReorderLinkedList {
    private static int SIZE = 10;   //-10, 0, 1, 2, 3, 10, 11
    private class LNode{
        int value;
        LNode next;
        LNode(int value, LNode next) {
            this.value = value;
            this.next = next;
        }
    }
    
    private void printLinkedList(LNode head) {
        LNode current = head;
        while(current != null) {
            System.out.print(current.value + "->");
            current = current.next;
        }
        System.out.println();
    }
    
    private LNode makeLinkedList() {
        LNode head = new LNode(-10, null);
        LNode current = head;
        for(int i = 0; i <= SIZE; i++) {
            current.next = new LNode(i, null);
            current = current.next;
        }
        return head;
    }
    
    //6->7->8->9->10
    private void reverseLinkedList(LNode head) {
        if(head == null || head.next == null) return;
        LNode pre = head;
        LNode current = pre.next;
        LNode next = current;
        while(current != null) {
            next = current.next;
            current.next = pre;
            pre = current;
            current = next;
        }
    }
    
    public static void main(String[] args) {
        ReorderLinkedList rl = new ReorderLinkedList();
        LNode head = rl.makeLinkedList();
        rl.printLinkedList(head.next);
        if(head == null || head.next == null || head.next.next == null) {
            System.out.println("nothing to do");
            return;
        }
        //find middle point and tail
        LNode fast = head.next;
        LNode slow = head.next;
        //1->2->3->4->5->6->7->8->9->10
        //            ,           .
        //1->2->3->4->5->6->7->8->9->10->11
        //               ,                .
        while(fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        
        //terminate the first half at the middle point, adjust tail
        LNode tail2 = (fast.next==null) ? fast : fast.next; 
        LNode head2 = slow.next;
        slow.next = null;
        
        //reverse the second half, tail2 pointer is *, head2 pointer is `
        //before 7`->8->9->10->11*
        rl.reverseLinkedList(head2);
        //after 11*->10->9->8->7`
        head2.next = null;
        
        //traversal first half, insert elements from second half
        LNode current1 = head.next;
        LNode current2 = tail2;
        LNode next1 = current1;
        LNode next2 = current2;
        while(!(current1 == null || current2 == null)) {
            next1 = current1.next;   //1->2*->3->4
            current1.next = current2;  //1->11
            next2 = current2.next;
            current2.next = next1;   //1->11->2*->3->4
            current1 = next1;
            current2 = next2;
        }
        rl.printLinkedList(head.next);
    }
}