Rearrange a given linked list in-place
Last Updated :
04 Sep, 2024
Given a singly linked list L0 -> L1 -> … -> Ln-1 -> Ln. Rearrange the nodes in the list so that the newly 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
Explanation: Here n = 4, so the correct order is L0->L3->L1->L2
Input: 1 -> 2 -> 3 -> 4 -> 5
Output: 1 -> 5 -> 2 -> 4 -> 3
Explanation: Here n = 4, so the correct order is L0->L4->L1->L3->L2
[Naive Approach] Using two nested loops- O(n^2) Time and O(1) Space
The idea is to start traversing from head node. For each node, perform the following operations:
- Traverse the list to find the last node.
- Disconnect the last node from the list.
- Place the removed last node after the current node.
- Update current to its next node.
[Efficient Approach] By Reversing Second Half - O(n) Time and O(1) Space
- Find the middle of the linked list using the fast and slow pointer method. This involves moving one pointer twice as fast as the other so that when the faster pointer reaches the end, the slower pointer will be at the middle.
- Reverse the second half of the list starting just after the middle node and split them in two parts.
- Merge the two halves together by alternating nodes from the first half with nodes from the reversed second half.
Below is the implementation of the above approach :
C++
// C++ code to rearrange a given linked list in-place
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node *next;
Node(int x) {
data = x;
next = NULL;
}
};
Node *reverselist(Node *head) {
Node *prev = nullptr, *curr = head, *next;
while (curr) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
void printList(Node *curr) {
while (curr != nullptr) {
cout << curr->data << " ";
curr = curr->next;
}
}
// Function to rearrange a linked list
Node *rearrange(Node *head) {
// Find the middle point using tortoise and hare method
Node *slow = head, *fast = slow->next;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
// Split the linked list into two halves
Node *head1 = head;
Node *head2 = slow->next;
slow->next = NULL;
// Reverse the second half
head2 = reverselist(head2);
// Merge alternate nodes
head = new Node(0);
Node *curr = head;
while (head1 || head2) {
// First add the element from the first list
if (head1) {
curr->next = head1;
curr = curr->next;
head1 = head1->next;
}
// Then add the element from the second list
if (head2) {
curr->next = head2;
curr = curr->next;
head2 = head2->next;
}
}
// Return the head of the new list
return head->next;
}
int main() {
// singly linked list 1->2->3->4->5
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);
head = rearrange(head);
printList(head);
return 0;
}
C
// C code to rearrange a given linked list in-place
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
struct Node *reverselist(struct Node *head) {
// Initialize prev and current pointers
struct Node *prev = NULL, *curr = head, *next;
while (curr) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
void printList(struct Node *curr) {
while (curr != NULL) {
printf("%d ", curr->data);
curr = curr->next;
}
}
// Function to rearrange a linked list
struct Node *rearrange(struct Node *head) {
// Find the middle point using tortoise
// and hare method
struct Node *slow = head, *fast = slow->next;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
// Split the linked list into two halves
// head1, head of first half
// head2, head of second half
struct Node *head1 = head;
struct Node *head2 = slow->next;
slow->next = NULL;
// Reverse the second half
head2 = reverselist(head2);
// Merge alternate nodes
struct Node dummy;
struct Node *curr = &dummy;
dummy.next = NULL;
while (head1 || head2) {
// First add the element from head1
if (head1) {
curr->next = head1;
curr = curr->next;
head1 = head1->next;
}
// Then add the element from head2
if (head2) {
curr->next = head2;
curr = curr->next;
head2 = head2->next;
}
}
return dummy.next;
}
struct Node *newNode(int key) {
struct Node *temp =
(struct Node *)malloc(sizeof(struct Node));
temp->data = key;
temp->next = NULL;
return temp;
}
int main() {
// singly linked list 1->2->3->4->5
struct Node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3);
head->next->next->next = newNode(4);
head->next->next->next->next = newNode(5);
head = rearrange(head);
printList(head);
return 0;
}
Java
// Java code to rearrange a given linked list in-place
class Node {
int data;
Node next;
Node(int d) {
data = d;
next = null;
}
}
class GfG {
static void printList(Node node) {
if (node == null) {
return;
}
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
}
static Node reverseList(Node node) {
Node prev = null, curr = node, next;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
// Method to rearrange the linked list
static Node rearrange(Node node) {
// Check if the list is empty or has only one node
if (node == null || node.next == null) {
return node;
}
// Find the middle point using tortoise and hare
// method
Node slow = node, fast = node.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// Split the linked list into two halves
Node firstHalf = node;
Node secondHalf = slow.next;
slow.next = null;
// Reverse the second half of the list
secondHalf = reverseList(secondHalf);
// Merge alternate nodes from the two halves
Node dummy = new Node(0);
Node curr = dummy;
while (firstHalf != null || secondHalf != null) {
if (firstHalf != null) {
curr.next = firstHalf;
curr = curr.next;
firstHalf = firstHalf.next;
}
if (secondHalf != null) {
curr.next = secondHalf;
curr = curr.next;
secondHalf = secondHalf.next;
}
}
// Return the new head of the rearranged list
return dummy.next;
}
public static void main(String[] args){
// singly linked list 1->2->3->4->5
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);
head = rearrange(head);
printList(head);
}
}
Python
# Python program to rearrange link list in place
class Node:
def __init__(self, d):
self.data = d
self.next = None
def printlist(node):
if node is None:
return
while node is not None:
print(node.data, end=" ")
node = node.next
def reverselist(node):
prev = None
curr = node
next = None
while curr is not None:
next = curr.next
curr.next = prev
prev = curr
curr = next
node = prev
return node
def rearrange(node):
# Find the middle point using the
# tortoise and hare method
slow = node
fast = slow.next
while fast is not None and fast.next is not None:
slow = slow.next
fast = fast.next.next
# Split the linked list into two halves
node1 = node
node2 = slow.next
slow.next = None
# Reverse the second half
node2 = reverselist(node2)
# Merge alternate nodes
node = Node(0)
curr = node
while node1 is not None or node2 is not None:
# Add the element from the first list
if node1 is not None:
curr.next = node1
curr = curr.next
node1 = node1.next
# Add the element from the second list
if node2 is not None:
curr.next = node2
curr = curr.next
node2 = node2.next
# Return the head of the rearranged list
return node.next
# singly linked list 1->2->3->4->5
head = None
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
head.next.next.next = Node(4)
head.next.next.next.next = Node(5)
head = rearrange(head)
printlist(head)
C#
// C# program to rearrange link list in place
using System;
public class Node {
public int Data;
public Node Next;
public Node(int data) {
Data = data;
Next = null;
}
}
class GfG {
static void PrintList(Node node) {
if (node == null) {
Console.WriteLine("List is empty.");
return;
}
while (node != null) {
Console.Write(node.Data + " ");
node = node.Next;
}
}
static Node ReverseList(Node node) {
Node prev = null;
Node curr = node;
Node next = null;
while (curr != null) {
next = curr.Next;
curr.Next = prev;
prev = curr;
curr = next;
}
return prev;
}
// Method to rearrange the linked list in-place and
// return the new head
static Node Rearrange(Node node) {
if (node == null || node.Next == null)
return node;
// Find the middle point using tortoise and hare
// method
Node slow = node;
Node fast = node.Next;
while (fast != null && fast.Next != null) {
slow = slow.Next;
fast = fast.Next.Next;
}
// Split the linked list into two halves
Node firstHalf = node;
Node secondHalf = slow.Next;
slow.Next = null;
// Reverse the second half
secondHalf = ReverseList(secondHalf);
// Merge alternate nodes
Node dummy = new Node(0);
Node curr = dummy;
while (firstHalf != null || secondHalf != null) {
if (firstHalf != null) {
curr.Next = firstHalf;
curr = curr.Next;
firstHalf = firstHalf.Next;
}
if (secondHalf != null) {
curr.Next = secondHalf;
curr = curr.Next;
secondHalf = secondHalf.Next;
}
}
// Return the new head of the list
return dummy.Next;
}
public static void Main(string[] args) {
//singly linked list 1->2->3->4->5
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);
head = Rearrange(head);
PrintList(head);
}
}
JavaScript
// Javascript program to rearrange link list in place
class Node {
constructor(d) {
this.data = d;
this.next = null;
}
}
function printList(node) {
let result = "";
while (node != null) {
result += node.data + " ";
node = node.next;
}
console.log(result);
}
function reverseList(node) {
let prev = null, curr = node, next;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
// Function to rearrange the linked list
function rearrange(head) {
if (head == null || head.next == null) {
return head;
}
// Find the middle point using
// tortoise and hare method
let slow = head, fast = slow.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// Split the linked list into two halves
let node1 = head;
let node2 = slow.next;
slow.next = null;
// Reverse the second half
node2 = reverseList(node2);
// Merge alternate nodes
let dummy = new Node(0);
let curr = dummy;
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;
}
}
return dummy.next;
}
// singly linked list 1->2->3->4->5
let 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);
head = rearrange(head);
printList(head);
Time Complexity: O(n) , where n are the number of nodes in linked list.
Auxiliary Space: O(1)