Java Program For Rearranging A Given Linked List In-Place.
Last Updated :
27 Jul, 2023
Given a singly linked list L0 -> L1 -> … -> Ln-1 -> Ln. Rearrange the nodes in the list so that the new formed list is : L0 -> Ln -> L1 -> Ln-1 -> L2 -> Ln-2 …
You are required to do this in place without altering the nodes’ values.
Examples:
Input: 1 -> 2 -> 3 -> 4
Output: 1 -> 4 -> 2 -> 3
Input: 1 -> 2 -> 3 -> 4 -> 5
Output: 1 -> 5 -> 2 -> 4 -> 3
Simple Solution:
1) Initialize current node as head.
2) While next of current node is not null, do following
a) Find the last node, remove it from the end and insert it as next
of the current node.
b) Move current to next to next of current
The time complexity of the above simple solution is O(n2) where n is the number of nodes in the linked list.
Better Solution:
1) Copy contents of the given linked list to a vector.
2) Rearrange the given vector by swapping nodes from both ends.
3) Copy the modified vector back to the linked list.
Implementation of this approach: https://ide.geeksforgeeks.org/1eGSEy
Thanks to Arushi Dhamija for suggesting this approach.
Efficient Solution:
1) Find the middle point using tortoise and hare method.
2) Split the linked list into two halves using found middle point in step 1.
3) Reverse the second half.
4) Do alternate merge of first and second halves.
The Time Complexity of this solution is O(n).
Below is the implementation of this method.
Java
class LinkedList
{
static Node head;
static class Node
{
int data;
Node next;
Node( int d)
{
data = d;
next = null ;
}
}
void printlist(Node node)
{
if (node == null )
{
return ;
}
while (node != null )
{
System.out.print(node.data);
if (node.next != null )
System.out.print( " -> " );
node = node.next;
}
}
Node reverselist(Node node)
{
Node prev = null ,
curr = node, next;
while (curr != null )
{
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
node = prev;
return node;
}
void rearrange(Node node)
{
Node slow = node, fast = slow.next;
while (fast != null &&
fast.next != null )
{
slow = slow.next;
fast = fast.next.next;
}
Node node1 = node;
Node node2 = slow.next;
slow.next = null ;
node2 = reverselist(node2);
node = new Node( 0 );
Node curr = node;
while (node1 != null ||
node2 != null )
{
if (node1 != null )
{
curr.next = node1;
curr = curr.next;
node1 = node1.next;
}
if (node2 != null )
{
curr.next = node2;
curr = curr.next;
node2 = node2.next;
}
}
node = node.next;
}
public static void main(String[] args)
{
LinkedList list = new LinkedList();
list.head = new Node( 1 );
list.head.next = new Node( 2 );
list.head.next.next =
new Node( 3 );
list.head.next.next.next =
new Node( 4 );
list.head.next.next.next.next =
new Node( 5 );
list.printlist(head);
list.rearrange(head);
System.out.println( "" );
list.printlist(head);
}
}
|
Output:
1 -> 2 -> 3 -> 4 -> 5
1 -> 5 -> 2 -> 4 -> 3
Time Complexity: O(n)
Auxiliary Space: O(1)
Thanks to Gaurav Ahirwar for suggesting the above approach.
Another approach:
1. Take two pointers prev and curr, which hold the addresses of head and head-> next.
2. Compare their data and swap.
After that, a new linked list is formed.
Below is the implementation:
Java
class Geeks
{
static class Node
{
int data;
Node next;
}
static Node rearrange(Node head)
{
if (head == null )
return null ;
Node prev = head,
curr = head.next;
while (curr != null )
{
if (prev.data > curr.data)
{
int t = prev.data;
prev.data = curr.data;
curr.data = t;
}
if (curr.next != null &&
curr.next.data > curr.data)
{
int t = curr.next.data;
curr.next.data = curr.data;
curr.data = t;
}
prev = curr.next;
if (curr.next == null )
break ;
curr = curr.next.next;
}
return head;
}
static Node push(Node head, int k)
{
Node tem = new Node();
tem.data = k;
tem.next = head;
head = tem;
return head;
}
static void display(Node head)
{
Node curr = head;
while (curr != null )
{
System.out.printf( "%d " ,
curr.data);
curr = curr.next;
}
}
public static void main(String args[])
{
Node head = null ;
head = push(head, 7 );
head = push(head, 3 );
head = push(head, 8 );
head = push(head, 6 );
head = push(head, 9 );
head = rearrange(head);
display(head);
}
}
|
Output:
6 9 3 8 7
Time Complexity : O(n)
Auxiliary Space : O(1)
Thanks to Aditya for suggesting this approach.
Another Approach: (Using recursion)
- Hold a pointer to the head node and go till the last node using recursion
- Once the last node is reached, start swapping the last node to the next of head node
- Move the head pointer to the next node
- Repeat this until the head and the last node meet or come adjacent to each other
- Once the Stop condition met, we need to discard the left nodes to fix the loop created in the list while swapping nodes.
Java
import java.io.*;
class Node
{
int data;
Node next;
Node( int key)
{
data = key;
next = null ;
}
}
class GFG
{
Node left = null ;
void printlist(Node head)
{
while (head != null )
{
System.out.print(head.data +
" " );
if (head.next != null )
{
System.out.print( "->" );
}
head = head.next;
}
System.out.println();
}
void rearrange(Node head)
{
if (head != null )
{
left = head;
reorderListUtil(left);
}
}
void reorderListUtil(Node right)
{
if (right == null )
{
return ;
}
reorderListUtil(right.next);
if (left == null )
{
return ;
}
if (left != right &&
left.next != right)
{
Node temp = left.next;
left.next = right;
right.next = temp;
left = temp;
}
else
{
if (left.next == right)
{
left.next.next = null ;
left = null ;
}
else
{
left.next = null ;
left = null ;
}
}
}
public static void main(String[] args)
{
Node head = new Node( 1 );
head.next = new Node( 2 );
head.next.next = new Node( 3 );
head.next.next.next =
new Node( 4 );
head.next.next.next.next =
new Node( 5 );
GFG gfg = new GFG();
gfg.printlist(head);
gfg.rearrange(head);
gfg.printlist(head);
}
}
|
Output:
1 ->2 ->3 ->4 ->5
1 ->5 ->2 ->4 ->3
Time Complexity: O(n), where n represents the length of the given linked list.
Auxiliary Space: O(n), for recursive stack where n represents the length of the given linked list.
Please refer complete article on Rearrange a given linked list in-place. for more details!
Share your thoughts in the comments
Please Login to comment...