LeetCode – Reorder List (Java)

Given a singly linked list L: L0→L1→ ... →Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→...

For example, given {1,2,3,4}, reorder it to {1,4,2,3}. You must do this in-place without altering the nodes' values.

Analysis

This problem is not straightforward, because it requires "in-place" operations. That means we can only change their pointers, not creating a new list.

Java Solution

This problem can be solved by doing the following:

  1. Break list in the middle to two lists (use fast & slow pointers)
  2. Reverse the order of the second list
  3. Merge two list back together

The following code is a complete runnable class with testing.

//Class definition of ListNode
class ListNode {
	int val;
	ListNode next;
 
	ListNode(int x) {
		val = x;
		next = null;
	}
}
 
public class ReorderList {
 
	public static void main(String[] args) {
		ListNode n1 = new ListNode(1);
		ListNode n2 = new ListNode(2);
		ListNode n3 = new ListNode(3);
		ListNode n4 = new ListNode(4);
		n1.next = n2;
		n2.next = n3;
		n3.next = n4;
 
		printList(n1);
 
		reorderList(n1);
 
		printList(n1);
	}
 
	public static void reorderList(ListNode head) {
 
		if (head != null && head.next != null) {
 
			ListNode slow = head;
			ListNode fast = head;
 
			//use a fast and slow pointer to break the link to two parts.
			while (fast != null && fast.next != null && fast.next.next!= null) {
				//why need third/second condition?
				System.out.println("pre "+slow.val + " " + fast.val);
				slow = slow.next;
				fast = fast.next.next;
				System.out.println("after " + slow.val + " " + fast.val);
			}
 
			ListNode second = slow.next;
			slow.next = null;// need to close first part
 
			// now should have two lists: head and fast
 
			// reverse order for second part
			second = reverseOrder(second);
 
			ListNode p1 = head;
			ListNode p2 = second;
 
			//merge two lists here
			while (p2 != null) {
				ListNode temp1 = p1.next;
				ListNode temp2 = p2.next;
 
				p1.next = p2;
				p2.next = temp1;		
 
				p1 = temp1;
				p2 = temp2;
			}
		}
	}
 
	public static ListNode reverseOrder(ListNode head) {
 
		if (head == null || head.next == null) {
			return head;
		}
 
		ListNode pre = head;
		ListNode curr = head.next;
 
		while (curr != null) {
			ListNode temp = curr.next;
			curr.next = pre;
			pre = curr;
			curr = temp;
		}
 
		// set head node's next
		head.next = null;
 
		return pre;
	}
 
	public static void printList(ListNode n) {
		System.out.println("------");
		while (n != null) {
			System.out.print(n.val);
			n = n.next;
		}
		System.out.println();
	}
}

Takeaway Messages

The three steps can be used to solve other problems of linked list. A little diagram may help better understand them.

Reverse List:

reverse-list

Merge List:

merge-list-in-place

Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • kd

    Here’s my solution for reorder list which I think is correct. Please let me know if I’m wrong.

    public node reorderList( node l)

    {

    node head = l;

    node reOrdered = null;

    if ( l == null || l.next == null)
    {

    } return l;

    while ( head.next != null)
    {

    reOrdered = head.next;

    while ( reOrdered.next != null)

    {

    reOrdered = reOrdered.next;

    }

    reOrdered.next=head.next;

    head.next = reOrdered;

    head = reOrdered.next;

    }

    return l;

    }

  • Salil Surendran

    If we can create a new list this solution would work:

    package com.salil.problemsolving;

    import com.salil.problemsolving.common.Node;

    /**
    * Created by salilsurendran on 3/1/2015.
    */
    public class ReorderList {

    public static void main(String[] args) {
    Node root = new Node(0);
    Node parentNode = root;
    for(int i=1;i<=10;i++){
    Node node = new Node(i);
    parentNode.child = node;
    parentNode = node;
    }

    Node reorderedNode = reOrderList(root);
    printList(reorderedNode);
    printList(reOrderList(new Node(0)));
    root = new Node(0);
    root.child = new Node(1);
    printList(reOrderList(root));

    }

    private static void printList(Node reorderedNode){
    while(reorderedNode != null){
    System.out.print(reorderedNode.value + " , ");
    reorderedNode = reorderedNode.child;
    }
    System.out.println();
    }

    private static Node reOrderList(Node root) {
    Node node = root;
    Node reverseRoot = null;
    Node childNode = null;
    int count = 0;
    while(node != null){
    reverseRoot = new Node(node.value);
    reverseRoot.child = childNode;
    childNode = reverseRoot;
    node = node.child;
    count++;
    }

    Node node1 = root;
    Node node2 = reverseRoot;
    Node childNode1 = null;
    Node childNode2 = null;
    Node previousNode2 = null;
    for(int i=0;i<count/2;i++){
    childNode1 = node1.child;
    childNode2 = node2.child;
    node1.child = node2;
    node2.child = childNode1;
    previousNode2 = node2;
    node2 = childNode2;
    node1 = childNode1;
    }

    if(count % 2 == 1)
    node1.child = null;
    else
    previousNode2.child = null;

    return root;

    }
    }

  • Crazy

    Excellent 🙂 Thanks a ton!

  • Zhisheng Zhou

    Thanks for this great solution.

    For this line:
    while (fast != null && fast.next != null && fast.next.next!= null)

    fast != null is not necessary.

    Best.

  • Isaac

    import java.util.*;

    public class ReorderList{

    public static void main(String[] args){

    ReorderList main = new ReorderList();

    ListNode list = new ListNode(1);
    list.next = new ListNode(2);
    list.next.next = new ListNode(3);
    list.next.next.next = new ListNode(4);

    main.reorderList(list);

    System.out.println(list.val + ” ” + list.next.val + ” ” +
    list.next.next.val + ” ” + list.next.next.next.val);

    }

    public void reorderList(ListNode node){

    ListNode current = node;

    // empty list or one-node list
    if(current == null || current.next == null) return;

    ListNode currentNext = current.next;
    ListNode l = currentNext;

    //base case
    if(currentNext.next == current || currentNext.next.next == current){
    currentNext.next = null;
    return;

    }

    //Use l to find the “next” node for current case
    //i.e., the node at position (list length – n)
    while(l.next != null){
    if(l.next.next == null)
    l = l.next;
    else if(l.next.next.next != current)
    l = l.next;
    }

    l.next = currentNext;
    current.next = l;

    reorderList(currentNext); //recursive call
    }
    }

    class ListNode{
    public int val;
    public ListNode next;

    public ListNode(int i){
    val = i;
    next = null;
    }
    }

  • Isaac

    import java.util.*;

    public class ReorderList{

    public static void main(String[] args){

    ReorderList main = new ReorderList();

    ListNode list = new ListNode(1);

    list.next = new ListNode(2);

    list.next.next = new ListNode(3);

    list.next.next.next = new ListNode(4);

    main.reorderList(list);

    System.out.println(list.val + ” ” + list.next.val + ” ” +

    list.next.next.val + ” ” + list.next.next.next.val);

    }

    public void reorderList(ListNode node){

    ListNode current = node;

    if(current == null || current.next == null) return;

    ListNode currentNext = current.next;

    ListNode l = currentNext;

    if(currentNext.next == current || currentNext.next.next == current){

    currentNext.next = null;

    return;

    }

    while(l.next != null){

    if(l.next.next == null)

    l = l.next;

    else if(l.next.next.next != current)

    l = l.next;

    }

    l.next = currentNext;

    current.next = l;

    reorderList(currentNext);

    }

    }

    class ListNode{

    public int val;

    public ListNode next;

    public ListNode(int i){

    val = i;

    next = null;

    }

    }

  • Emilio

    Nice solution, just one typo, len%2==0 should be count%2==0

  • jason

    recursive solution without reverse

  • jason

    package test;

    /*
    * Given a singly linked list L: L0→L1→ … →Ln-1→Ln,
    reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
    */
    public class ReorderList {

    static class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
    val = x;
    next = null;
    }
    }

    int len=0;
    public void order(ListNode head) {

    //calculate len;
    ListNode current=head;
    len=1;
    while (current.next!=null) {
    len++;
    current=current.next;
    }

    /**
    * 0-1-2-3-> 0-3->1-2
    * 0-1-2-3-4 -> 0-4-1-3-2
    */
    int count=(len%2==0)?len/2-1:len/2;
    ListNode newchild=recursiveForward(head, count);
    }

    public ListNode recursiveForward(ListNode current, int count) {
    if (count==0) {
    if (len%2==0) {
    ListNode forward=current.next.next;
    current.next.next=null;
    return forward;
    } else {
    ListNode forward=current.next;
    current.next=null;
    return forward;
    }
    } else {
    ListNode newNextListNode=recursiveForward(current.next, count-1);

    ListNode forward=newNextListNode.next;
    newNextListNode.next=current.next;
    current.next=newNextListNode;
    return forward;
    }
    }

    public static void main(String[] args) {
    ListNode head, current;
    ReorderList reorderList;

    //0,1,2,3
    head=new ListNode(0);
    current=head;
    for (int i = 1; i <=3; i++) {
    ListNode newNode=new ListNode(i);
    current.next=newNode;
    current=newNode;
    }
    outputList(head);
    reorderList=new ReorderList();
    reorderList.order(head);
    outputList(head);

    //0,1,2,3,4
    head=new ListNode(0);
    current=head;
    for (int i = 1; i <=4; i++) {
    ListNode newNode=new ListNode(i);
    current.next=newNode;
    current=newNode;
    }
    outputList(head);
    reorderList=new ReorderList();
    reorderList.order(head);

    outputList(head);
    }

    public static void outputList(ListNode head) {
    while(head!=null) {
    System.out.print(head.val+" ");
    head=head.next;
    }
    System.out.println(" ");
    }
    }