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.
Java Solution
Because the problem requires “in-place” operations, we can only change their pointers, not creating a new list. This problem can be solved by doing the following 3 steps:
- Break list in the middle to two lists (use fast & slow pointers)
- Reverse the order of the second list
- 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. The following diagrams illustrate how each of the steps works.
Reverse List:
Merge List:
Note that pointers movements always starts with assigning the next node to a temporary variable t.
==other solution would be ==
keep pointer to start
recursive traverse to end of list
unwind travel and start adding nodes from end to node (parameter)
# reorder list
obv we need just in recurse reach end of list (keeping start as parameter)
on unwind insert=add nodes from end from start
my recursive solution
reorder(YourList,size-1); //call this in main
private static void reorder(NodeLL root,int size) {
//here put stupid validation
if(size==0){root.next=null;return;}//this occurs when size of list odd
if(size==1){root.next.next=null;return;}//this occurs when size of list even
NodeLL curr = root;
NodeLL end =root;
int i = 0;
while (i < size){
end =end.next;
++i;
}
NodeLL temp = curr.next;
curr.next = end;
end.next = temp;
reorder(temp,size-2);
}
This is my solution with recursion
Node root;//Your list
int size; //size of your list
reorder(root,size-1); //call in main first time in function with size-1
private void reorder(Node root,int size) {
//there should be stupid validations
if(size==0){root.next=null;return;}//this occurs when List is odd size
if(size==1){root.next.next=null;return;}//this occurs when List is even size
Node curr = root;
Node end1 =root;
int i = 0;
while (i<size){ end1 = end1.next;
++i;
};
Node temp = curr.next;
curr.next = end1;
end1.next = temp;
reorder(temp,size-2);
};
//Please vote up if you like!
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;
}
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;
}
}
Excellent 🙂 Thanks a ton!
Thanks for this great solution.
For this line:
while (fast != null && fast.next != null && fast.next.next!= null)
fast != null is not necessary.
Best.
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;
}
}
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;
}
}
Nice solution, just one typo, len%2==0 should be count%2==0
recursive solution without reverse
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(" ");
}
}