Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Reverse a doubly linked list in groups of given size | Set 2

  • Difficulty Level : Expert
  • Last Updated : 28 Jan, 2022

Given a doubly-linked list containing n nodes. The problem is to reverse every group of k nodes in the list.

Examples: 

Input: List: 10<->8<->4<->2, K=2
Output: 8<->10<->2<->4

Input: List: 1<->2<->3<->4<->5<->6<->7<->8, K=3
Output: 3<->2<->1<->6<->5<->4<->8<->7

Recursive Approach: The recursive approach to solving this problem is discussed in Set-1 of this article. Here, we are discussing the iterative approach.

Iterative Approach: This approach is a mix of two algorithms – reversing a doubly-linked list and reversing a linked list in a group of a given size. The function reverseK() individually reverses every k size linked list and connects them using prevFirst pointer that keeps track of the node that is bound to come after reversing. Follow the steps below to solve this problem:

  • If N is less than equal to 1, then return head.
  • Initialize the variables prevFirst as nullptr and curr as head.
  • Initialize the variable firstPass as true.
  • Traverse over a while loop till curr is not equal to null and perform the following tasks:
    • Initialize the variable count as 0.
    • Initialize the variables first as curr, next and prev as null.
    • Traverse over a while loop till curr is not equal to null and count is less than K and perform the following tasks:
      • Set the value of next as curr->next.
      • If count equals 0 then set curr->next as null else curr->next as curr->prev.
      • Set curr->prev as next, prev as curr and curr as next.
      • Increase the value of count by 1.
      • If firstPass is true then set head as next->prev and firstPass as false.
      • Else, set prevFirst->next as prev.
      • Set prevFirst as first.
  • After performing the above steps, print the value of head as the answer.

Below is the implementation of the above approach.

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// A linked list node
class Node {
public:
    int data;
    Node* next;
    Node* prev;
};
 
// Given a reference (pointer to pointer)
// to the head of a list
// and an int, inserts a new node on the
// front of the list.
void push(Node** head_ref, int new_data)
{
 
    // Allocate node
    Node* new_node = new Node();
 
    // Put in the data
    new_node->data = new_data;
 
    // Make next of new node as head
    // and previous as NULL
    new_node->next = (*head_ref);
    new_node->prev = NULL;
 
    // Change prev of head node to new node
    if ((*head_ref) != NULL)
        (*head_ref)->prev = new_node;
 
    // Move the head to point to the new node
    (*head_ref) = new_node;
}
 
// Given a node as prev_node, insert
// a new node after the given node
void insertAfter(Node* prev_node, int new_data)
{
 
    // Check if the given prev_node is NULL
    if (prev_node == NULL) {
        cout << "the given previous "
             << "node cannot be NULL";
        return;
    }
 
    // Allocate new node
    Node* new_node = new Node();
 
    // Put in the data
    new_node->data = new_data;
 
    // Make next of new node as next of prev_node
    new_node->next = prev_node->next;
 
    // Make the next of prev_node as new_node
    prev_node->next = new_node;
 
    // Make prev_node as previous of new_node
    new_node->prev = prev_node;
 
    // Change previous of new_node's next node
    if (new_node->next != NULL)
        new_node->next->prev = new_node;
}
 
// Given a reference (pointer to pointer) to the head
// of a DLL and an int, appends a new node at the end
void append(Node** head_ref, int new_data)
{
 
    // Allocate node
    Node* new_node = new Node();
 
    Node* last = *head_ref;
 
    // Put in the data
    new_node->data = new_data;
 
    // This new node is going to be the last node,
    // so make next of it as NULL
    new_node->next = NULL;
 
    // If the Linked List is empty,
    // then make the new
    // node as head
    if (*head_ref == NULL) {
        new_node->prev = NULL;
        *head_ref = new_node;
        return;
    }
 
    // Else traverse till the last node
    while (last->next != NULL)
        last = last->next;
 
    // Change the next of last node
    last->next = new_node;
 
    // Make last node as previous of new node
    new_node->prev = last;
 
    return;
}
 
// This function prints contents of
// linked list starting from the given node
void printList(Node* node)
{
    Node* last;
    while (node != NULL) {
        cout << " " << node->data << " ";
        last = node;
        node = node->next;
    }
}
 
Node* reverseK(Node* head, int k)
{
 
    // When head is NULL or linked list
    // has a single node we return
    if (head == NULL || head->next == NULL)
        return head;
 
    // PrevFirst pointer keeps track of
    // the node that is to be connected to each
    // reversed part.
    Node *prevFirst = NULL, *curr = head;
 
    // FirstPass variable is used so that we
    // can mark head of the new linkedlist.
    bool firstPass = true;
 
    while (curr != NULL) {
        int count = 0;
 
        // Next keeps track of the next node of curr
        // Prev keeps track of the previous node of curr
 
        Node *first = curr, *next = NULL, *prev = NULL;
        while (curr != NULL && count < k) {
 
            // Reversing the doubly linked list by just
            // swapping their next and prev pointers
            next = curr->next;
            if (count == 0)
                curr->next = NULL;
            else
                curr->next = curr->prev;
            curr->prev = next;
            prev = curr;
            curr = next;
            count++;
        }
        if (firstPass) {
 
            // Setting the head of the new linkedlist
            head = next->prev;
            firstPass = false;
        }
        else {
            prevFirst->next = prev;
        }
        prevFirst = first;
    }
    return head;
}
 
// Driver Code
int main()
{
 
    // Start with the empty list
    Node* head = NULL;
 
    // Insert 6. So linked list becomes 6->NULL
    append(&head, 6);
 
    // Insert 7 at the beginning. So
    // linked list becomes 7->6->NULL
    push(&head, 7);
 
    // Insert 1 at the beginning. So
    // linked list becomes 1->7->6->NULL
    push(&head, 1);
 
    // Insert 4 at the end. So linked
    // list becomes 1->7->6->4->NULL
    append(&head, 4);
 
    // Insert 8, after 7. So linked
    // list becomes 1->7->8->6->4->NULL
    insertAfter(head->next, 8);
 
    // list becomes 1->7->8->6->4->9->NULL
    append(&head, 9);
    head = reverseK(head, 2);
    printList(head);
 
    return 0;
}

Java




// Java program for the above approach
import java.util.*;
 
class GFG{
 
// A linked list node
static class Node {
    int data;
    Node next;
    Node prev;
};
static Node head = null;
   
// Given a reference (pointer to pointer)
// to the head of a list
// and an int, inserts a new node on the
// front of the list.
static void push(int new_data)
{
 
    // Allocate node
    Node new_node = new Node();
 
    // Put in the data
    new_node.data = new_data;
 
    // Make next of new node as head
    // and previous as null
    new_node.next = head;
    new_node.prev = null;
 
    // Change prev of head node to new node
    if (head != null)
        head.prev = new_node;
 
    // Move the head to point to the new node
    head = new_node;
}
 
// Given a node as prev_node, insert
// a new node after the given node
static void insertAfter(Node prev_node, int new_data)
{
 
    // Check if the given prev_node is null
    if (prev_node == null) {
        System.out.print("the given previous "
            + "node cannot be null");
        return;
    }
 
    // Allocate new node
    Node new_node = new Node();
 
    // Put in the data
    new_node.data = new_data;
 
    // Make next of new node as next of prev_node
    new_node.next = prev_node.next;
 
    // Make the next of prev_node as new_node
    prev_node.next = new_node;
 
    // Make prev_node as previous of new_node
    new_node.prev = prev_node;
 
    // Change previous of new_node's next node
    if (new_node.next != null)
        new_node.next.prev = new_node;
}
 
// Given a reference (pointer to pointer) to the head
// of a DLL and an int, appends a new node at the end
static void append(int new_data)
{
 
    // Allocate node
    Node new_node = new Node();
 
    Node last = head;
 
    // Put in the data
    new_node.data = new_data;
 
    // This new node is going to be the last node,
    // so make next of it as null
    new_node.next = null;
 
    // If the Linked List is empty,
    // then make the new
    // node as head
    if (head == null) {
        new_node.prev = null;
        head = new_node;
        return;
    }
 
    // Else traverse till the last node
    while (last.next != null)
        last = last.next;
 
    // Change the next of last node
    last.next = new_node;
 
    // Make last node as previous of new node
    new_node.prev = last;
 
    return;
}
 
// This function prints contents of
// linked list starting from the given node
static void printList(Node node)
{
    Node last = new Node();
    while (node != null) {
        System.out.print(" " +  node.data+ " ");
        last = node;
        node = node.next;
    }
}
 
static Node reverseK(Node head, int k)
{
 
    // When head is null or linked list
    // has a single node we return
    if (head == null || head.next == null)
        return head;
 
    // PrevFirst pointer keeps track of
    // the node that is to be connected to each
    // reversed part.
    Node prevFirst = null, curr = head;
 
    // FirstPass variable is used so that we
    // can mark head of the new linkedlist.
    boolean firstPass = true;
 
    while (curr != null) {
        int count = 0;
 
        // Next keeps track of the next node of curr
        // Prev keeps track of the previous node of curr
 
        Node first = curr, next = null, prev = null;
        while (curr != null && count < k) {
 
            // Reversing the doubly linked list by just
            // swapping their next and prev pointers
            next = curr.next;
            if (count == 0)
                curr.next = null;
            else
                curr.next = curr.prev;
            curr.prev = next;
            prev = curr;
            curr = next;
            count++;
        }
        if (firstPass) {
 
            // Setting the head of the new linkedlist
            head = next.prev;
            firstPass = false;
        }
        else {
            prevFirst.next = prev;
        }
        prevFirst = first;
    }
    return head;
}
 
// Driver Code
public static void main(String[] args)
{
 
    // Start with the empty list
    head = null;
 
    // Insert 6. So linked list becomes 6.null
    append( 6);
 
    // Insert 7 at the beginning. So
    // linked list becomes 7.6.null
    push(7);
 
    // Insert 1 at the beginning. So
    // linked list becomes 1.7.6.null
    push(1);
 
    // Insert 4 at the end. So linked
    // list becomes 1.7.6.4.null
    append( 4);
 
    // Insert 8, after 7. So linked
    // list becomes 1.7.8.6.4.null
    insertAfter(head.next, 8);
 
    // list becomes 1.7.8.6.4.9.null
    append( 9);
    head = reverseK(head, 2);
    printList(head);
 
}
}
 
// This code contributed by shikhasingrajput

C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG{
 
  // A linked list node
  class Node {
    public int data;
    public Node next;
    public Node prev;
  };
  static Node head = null;
 
  // Given a reference (pointer to pointer)
  // to the head of a list
  // and an int, inserts a new node on the
  // front of the list.
  static void push(int new_data)
  {
 
    // Allocate node
    Node new_node = new Node();
 
    // Put in the data
    new_node.data = new_data;
 
    // Make next of new node as head
    // and previous as null
    new_node.next = head;
    new_node.prev = null;
 
    // Change prev of head node to new node
    if (head != null)
      head.prev = new_node;
 
    // Move the head to point to the new node
    head = new_node;
  }
 
  // Given a node as prev_node, insert
  // a new node after the given node
  static void insertAfter(Node prev_node, int new_data)
  {
 
    // Check if the given prev_node is null
    if (prev_node == null) {
      Console.Write("the given previous "
                    + "node cannot be null");
      return;
    }
 
    // Allocate new node
    Node new_node = new Node();
 
    // Put in the data
    new_node.data = new_data;
 
    // Make next of new node as next of prev_node
    new_node.next = prev_node.next;
 
    // Make the next of prev_node as new_node
    prev_node.next = new_node;
 
    // Make prev_node as previous of new_node
    new_node.prev = prev_node;
 
    // Change previous of new_node's next node
    if (new_node.next != null)
      new_node.next.prev = new_node;
  }
 
  // Given a reference (pointer to pointer) to the head
  // of a DLL and an int, appends a new node at the end
  static void append(int new_data)
  {
 
    // Allocate node
    Node new_node = new Node();
 
    Node last = head;
 
    // Put in the data
    new_node.data = new_data;
 
    // This new node is going to be the last node,
    // so make next of it as null
    new_node.next = null;
 
    // If the Linked List is empty,
    // then make the new
    // node as head
    if (head == null) {
      new_node.prev = null;
      head = new_node;
      return;
    }
 
    // Else traverse till the last node
    while (last.next != null)
      last = last.next;
 
    // Change the next of last node
    last.next = new_node;
 
    // Make last node as previous of new node
    new_node.prev = last;
 
    return;
  }
 
  // This function prints contents of
  // linked list starting from the given node
  static void printList(Node node)
  {
    Node last = new Node();
    while (node != null) {
      Console.Write(" " +  node.data+ " ");
      last = node;
      node = node.next;
    }
  }
 
  static Node reverseK(Node head, int k)
  {
 
    // When head is null or linked list
    // has a single node we return
    if (head == null || head.next == null)
      return head;
 
    // PrevFirst pointer keeps track of
    // the node that is to be connected to each
    // reversed part.
    Node prevFirst = null, curr = head;
 
    // FirstPass variable is used so that we
    // can mark head of the new linkedlist.
    bool firstPass = true;
 
    while (curr != null) {
      int count = 0;
 
      // Next keeps track of the next node of curr
      // Prev keeps track of the previous node of curr
 
      Node first = curr, next = null, prev = null;
      while (curr != null && count < k) {
 
        // Reversing the doubly linked list by just
        // swapping their next and prev pointers
        next = curr.next;
        if (count == 0)
          curr.next = null;
        else
          curr.next = curr.prev;
        curr.prev = next;
        prev = curr;
        curr = next;
        count++;
      }
      if (firstPass) {
 
        // Setting the head of the new linkedlist
        head = next.prev;
        firstPass = false;
      }
      else {
        prevFirst.next = prev;
      }
      prevFirst = first;
    }
    return head;
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
 
    // Start with the empty list
    head = null;
 
    // Insert 6. So linked list becomes 6.null
    append( 6);
 
    // Insert 7 at the beginning. So
    // linked list becomes 7.6.null
    push(7);
 
    // Insert 1 at the beginning. So
    // linked list becomes 1.7.6.null
    push(1);
 
    // Insert 4 at the end. So linked
    // list becomes 1.7.6.4.null
    append( 4);
 
    // Insert 8, after 7. So linked
    // list becomes 1.7.8.6.4.null
    insertAfter(head.next, 8);
 
    // list becomes 1.7.8.6.4.9.null
    append( 9);
    head = reverseK(head, 2);
    printList(head);
 
  }
}
 
// This code is contributed by 29AjayKumar
Output
 7  1  6  8  9  4 

Time Complexity: O(N)
Auxiliary Space: O(1)


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!