Learnitweb

Reversing the linked list in place (without using extra space)

The goal is to reverse the linked list such that:

  • The head node becomes the tail.
  • The tail node becomes the head.
  • Every node’s next pointer should point to its previous node.
  • If it is a doubly linked list (DLL), you also need to swap the previous pointers.

Approach 1: Reversing a Singly Linked List (SLL)

Logic

Given a singly linked list like this:

Head -> [1] -> [2] -> [3] -> [4] -> [5] -> null

We need to reverse it to:

null <- [1] <- [2] <- [3] <- [4] <- [5] <- Head

Steps to Reverse

Initialize three pointers:

  • Previous (prev) → Initially null.
  • Current (curr) → Points to the head.
  • Next (next) → To temporarily store the next node.

Traverse the list:

  • Break the next link (curr.next).
  • Reverse the link (curr.next = prev).
  • Move the prev and curr pointers one step forward.

Once the loop completes, prev will point to the new head.

Java Code to Reverse a Singly Linked List In-Place

Here is the Java code to reverse a singly linked list:

class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
        this.next = null;
    }
}

public class LinkedList {
    Node head;

    // Function to reverse the linked list in-place
    public void reverse() {
        Node prev = null;
        Node curr = head;
        Node next = null;

        while (curr != null) {
            // Store the next node
            next = curr.next;
            // Reverse the link
            curr.next = prev;
            // Move pointers one step ahead
            prev = curr;
            curr = next;
        }
        // Update the head to the new first node
        head = prev;
    }

    // Insert function
    public void insert(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
    }

    // Function to print the linked list
    public void printList() {
        Node temp = head;
        while (temp != null) {
            System.out.print(temp.data + " -> ");
            temp = temp.next;
        }
        System.out.println("null");
    }

    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        list.insert(1);
        list.insert(2);
        list.insert(3);
        list.insert(4);
        list.insert(5);

        System.out.println("Original Linked List:");
        list.printList();

        list.reverse();
        System.out.println("Reversed Linked List:");
        list.printList();
    }
}

Output

Original Linked List:
1 -> 2 -> 3 -> 4 -> 5 -> null

Reversed Linked List:
5 -> 4 -> 3 -> 2 -> 1 -> null

Explanation

  • We simply reverse the pointers (nextprev) during traversal.
  • Once the traversal ends, the prev becomes the new head of the list.
  • This approach uses:
    • O(n) time complexity (because we traverse once).
    • O(1) space complexity (because we only use three pointers).

Approach 2: Reverse a Doubly Linked List (DLL) In-Place

In a doubly linked list (DLL), each node has:

  • next → Points to the next node.
  • prev → Points to the previous node.

The logic here is slightly different since you need to:

  • Swap the next and prev pointers of each node.
  • After the traversal, update the head to the last node.

Java Code to Reverse a Doubly Linked List In-Place

class Node {
    int data;
    Node next;
    Node prev;

    Node(int data) {
        this.data = data;
        this.next = null;
        this.prev = null;
    }
}

public class DoublyLinkedList {
    Node head;

    // Function to reverse the DLL in-place
    public void reverse() {
        Node curr = head;
        Node temp = null;

        // Traverse the list and swap next and prev pointers
        while (curr != null) {
            temp = curr.prev;
            curr.prev = curr.next;
            curr.next = temp;
            curr = curr.prev;
        }

        // After the loop, reset the head
        if (temp != null) {
            head = temp.prev;
        }
    }

    // Insert function
    public void insert(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
        newNode.prev = temp;
    }

    // Function to print the linked list
    public void printList() {
        Node temp = head;
        while (temp != null) {
            System.out.print(temp.data + " <-> ");
            temp = temp.next;
        }
        System.out.println("null");
    }

    public static void main(String[] args) {
        DoublyLinkedList list = new DoublyLinkedList();
        list.insert(1);
        list.insert(2);
        list.insert(3);
        list.insert(4);
        list.insert(5);

        System.out.println("Original DLL:");
        list.printList();

        list.reverse();
        System.out.println("Reversed DLL:");
        list.printList();
    }
}

Explanation

  • In a doubly linked list, you simply swap the next and prev pointers of each node.
  • Once you finish the loop, you make the last node as the new head.
  • This is done in-place without extra space.

Output

Original DLL:
1 <-> 2 <-> 3 <-> 4 <-> 5 <-> null

Reversed DLL:
5 <-> 4 <-> 3 <-> 2 <-> 1 <-> null

Why Is This Approach Considered In-Place?

  • No new nodes are created.
  • We only modify the existing pointers.
  • It uses constant space (O(1)) for pointers.
  • Time complexity is O(n).