Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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


Python3




# Python Code for the above problem.
 
# Node class
 
 
class Node:
 
        # Function to initialise the node object
    def __init__(self, data):
        self.data = data  # Assign data
        self.next = None  # Initialize next as null
        self.prev = None  # Initialize previous as null
 
# Linked List class contains a Node object
 
 
class LinkedList:
 
        # Function to initialize head
    def __init__(self):
        self.head = None
 
    # Function to insert a new node at the beginning
    def push(self, new_data):
        new_node = Node(new_data)
        new_node.next = self.head
        new_node.prev = None
        if self.head is not None:
            self.head.prev = new_node
        self.head = new_node
 
    # This function is in LinkedList class. Inserts a
    # new node after the given prev_node.
    def insertAfter(self, prev_node, new_data):
        if prev_node is None:
            return
        new_node = Node(new_data)
        new_node.next = prev_node.next
        prev_node.next = new_node
        new_node.prev = prev_node
        if new_node.next is not None:
            new_node.next.prev = new_node
 
    # This function is defined in Linked List class
    # Appends a new node at the end.
    def append(self, new_data):
        new_node = Node(new_data)
        last = self.head
        if self.head is None:
            new_node.prev = None
            self.head = new_node
            return
        while (last.next):
            last = last.next
        last.next = new_node
        new_node.prev = last
 
    # Utility function to print the linked list
    def printList(self):
        temp = self.head
        while(temp):
            print(temp.data, end=" ")
            temp = temp.next
 
    def reverseK(self, k):
        # When head is NULL or linked list
        # has a single node we return
        if self.head is None or self.head.next is None:
            return
 
        # PrevFirst pointer keeps track of
        # the node that is to be connected to each
        # reversed part.
        prevFirst, curr = None, self.head
 
        # FirstPass variable is used so that we
        # can mark head of the new linkedlist.
        firstPass = True
        while curr:
            count = 0
 
            # Next keeps track of the next node of curr
            # Prev keeps track of the previous node of curr
            first, next_node, prev_node = curr, None, None
            while curr is not None and count < k:
                # Reversing the doubly linked list by just
                # swapping their next and prev pointers
                next_node = curr.next
                if count is 0:
                    curr.next = None
                else:
                    curr.next = curr.prev
                curr.prev = next_node
                prev_node = curr
                curr = next_node
                count += 1
 
            if (firstPass):
                # Setting the head of the new linkedlist
                self.head = next_node.prev
                firstPass = False
            else:
                prevFirst.next = prev_node
 
            prevFirst = first
        return self.head
 
 
if __name__ == '__main__':
 
    llist = LinkedList()
 
    # Insert 6. So linked list becomes 6->NULL
    llist.append(6)
 
    # Insert 7 at the beginning. So
    # linked list becomes 7->6->NULL
    llist.push(7)
 
    # Insert 1 at the beginning. So
    # linked list becomes 1->7->6->NULL
    llist.push(1)
 
    # Insert 4 at the end. So linked
    # list becomes 1->7->6->4->NULL
    llist.append(4)
 
    # Insert 8, after 7. So linked
    # list becomes 1->7->8->6->4->NULL
    llist.insertAfter(llist.head.next, 8)
 
    # list becomes 1->7->8->6->4->9->NULL
    llist.append(9)
    llist.reverseK(2)
    llist.printList()
 
    # This code is contributed by lokesh (lokeshmvs21).


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


Javascript




// JavaScript program for the above approach
class Node{
    constructor(data){
        this.data = data;
        this.next = null;
        this.prev = 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.
function push(head_ref, new_data){
    // allocate node
    let new_node = new Node(new_data);
     
    // make next of new node as head
    new_node.next = head_ref;
     
    // change prev of head node to new node
    if(head_ref != null) head_ref.prev = new_node;
     
    head_ref = new_node;
    return head_ref;
}
 
// Given a node as prev_node, insert
// a new node after the given node
function insertAfter(prev_node, new_data){
    // check if the given prev_node is null
    if(prev_node == null){
        document.write("the given previous node cannot be NULL");
        return;
    }
     
    // allocate new node
    let new_node = new Node(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
function append(head_ref, new_data){
    // Allocate node
    let new_node = new Node(new_data);
  
    let last = head_ref;
  
    // 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 head_ref;
    }
  
    // 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 head_ref;
}
 
// This function prints contents of
// linked list starting from the given node
function printList(node){
    let last;
    while(node != null){
        document.write(node.data + " ");
        last = node;
        node = node.next;
    }
}
 
function reverseK(head, 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.
    let prevFirst = null;
    let curr = head;
     
    // FirstPass variable is used so that we
    // can mark head of the new linkedlist.
    let firstPass = true;
     
    while(curr != null){
        let count = 0;
         
        // Next keeps track of the next node of curr
        // Prev keeps track of the previous node of curr
        let first = curr;
        let next = null;
        let 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
// start with the empty list
let head = null;
 
// Insert 6. So linked list becomes 6->NULL
head = append(head, 6);
 
// Insert 7 at the beginning. So
// linked list becomes 7->6->NULL
head = push(head, 7);
 
// Insert 1 at the beginning. So
// linked list becomes 1->7->6->NULL
head = push(head, 1);
 
// Insert 4 at the end. So linked
// list becomes 1->7->6->4->NULL
head = 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
head = append(head, 9);
 
head = reverseK(head, 2);
printList(head);
 
// This code is contributed by Kirti Agarwal


Output

 7  1  6  8  9  4 

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



Last Updated : 02 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads