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<->4Input: 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++ 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 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 |
# 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# 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 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 |
7 1 6 8 9 4
Time Complexity: O(N)
Auxiliary Space: O(1)