Open-Source Internship opportunity by OpenGenus for programmers. Apply now.
We are given a pointer to the head of a singly Linked List and you have to write a function to reverse the elements of the given singly Linked List in alternate groups of K nodes. Once the operation is performed, pointer to the head of the Linked List must be returned from the function.
Input: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10
and
k = 3
Output: 3 -> 2 -> 1 -> 4 -> 5 -> 6 -> 9 -> 8 -> 7 -> 10
In the above example, k is equal to 3. Therefore we are required to reverse the elements of the linked list in alternate groups of 3 i.e. we reverse first 3 elements 1 β 2 β 3
to 3 β 2 β 1
, then keep next 3 elements in same order i.e. 4 β 5 β 6
and repeat this process for remaining nodes. As a result of the above operation we obtain the linked list having elements 3 β 2 β 1 β 4 β 5 β 6 β 9 β 8 β 7 β 10
and in that order.
We have explored two approaches:
- Recursive implementation
- Iterative implementation
Complexity
- Time Complexity:
O(n)
- Space Complexity:
O(1)
Approach 1: Recursive Implementation
Algorithm
Step 1: Reverse first K elements in the Linked List. While doing that let curr be current node, prev be previous node of curr and next be node pointed by curr->next.
Step 2: Skip reversing next K nodes.
Step 3: Now, recursively call reverseKGroupAltRecursive(curr.next, k) where curr.next points to the (2K+1)-th node and the pointer to resultant list returned by the function is stored in curr->next where curr currently points to 2K-th node.
Step 3: Return prev as it now points to the head of resultant list.
Pseudocode
reverseKGroupAltRecursive(head, k)
curr = head
prev = nullptr
next = nullptr
count = 0
WHILE count < k AND curr
next = curr.next
curr.next = prev
prev = curr
curr = next
count = count + 1
IF head
head.next = curr
count = 0
WHILE count < k-1 AND curr
curr = curr.next
count = count + 1
IF curr
curr.next = reverseKGroupAltRecursive(curr.next, k)
return prev
Implementation
Following is the C++ implementation:
#include <iostream>
using namespace std;
struct Node {
int val;
struct Node *next;
Node(int x): val(x), next(nullptr) {}
};
Node* reverseKGroupAltRecursive(Node *head, int k) {
struct Node *curr = head;
struct Node *prev = nullptr;
struct Node *next = nullptr;
// Reverse nodes in groups of k
int count = 0;
while(count < k && curr != nullptr) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
count++;
}
// Make K-th node (head) point to K+1-th node (curr)
if(head != nullptr)
head->next = curr;
// skip next K-1 nodes
count = 0;
while(count < k-1 && curr != nullptr) {
curr = curr->next;
count++;
}
// Check if the end of linked list is reached
// If not, then make a recursive call to alternatively reverse remaining nodes
if(curr != nullptr)
curr->next = reverseKGroupAltRecursive(curr->next, k);
return prev;
}
int main() {
// Creating singly linked list
// 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
struct Node *head = new Node(1);
struct Node *curr = head;
for(int i=2;i<=8;i++) {
curr->next = new Node(i);
curr = curr->next;
}
// Initialize k
int k = 3;
// Reverse first K nodes of linked list
head = reverseKGroupAltRecursive(head, k);
// Print list elements
while(head) {
cout<<head->val<<" ";
head = head->next;
}
cout<<endl;
return 0;
}
Explanation
- Consider singly linked list where Node pointer head points to first node in
1 β 2 β 3 β 4 β 5 β 6 β 7 β 8
and let k = 3. - Three Node pointers curr, prev and next are created having values of head, NULL and NULL.
- Now, we try to reverse the first K nodes i.e. 3 nodes of the linked list inside the while loop. We loop through the list as long as count value is less than k and curr is not NULL.
- During each iteration each node is reversed and prev points to the reversed linked list i.e. after first iteration prev points to
1
and next points to2 β 3 β 4 β 5 β 6 β 7 β 8
, after second iteration prev points to2 β 1
and next points to3 β 4 β 5 β 6 β 7 β 8
and after third iteration prev points to3 β 2 β 1
and next points to4 β 5 β 6 β 7 β 8
after which the loop breaks as count is equal to k. - head points to the K-th node in reversed linked list i.e. head points to 1 in
3 β 2 β 1
as it's pointer value remains unchanged. - If head is not NULL, make head.next point to curr where curr points to the remaining nodes to be processed in the linked list. This operation joins the tail of reversed linked list to the head of remaining linked list to be processed.
- Now we skip the next K nodes using a while loop as we are reversing the linked list in alternative groups of K. We skip until 2K-th node is reached and exit the loop. curr points to 2K-th node. The linked list we have processed so far is
3 β 2 β 1 β 4 β 5 β 6
and curr points to node with value 6. Still7 β 8
are yet to be processed. - If curr is not NULL, we make a recursive call to reverseKGroupAltRecursive function to alternatively reverse nodes from (2K+1)-th positon which is pointed by the pointer curr.next and the above process repeats. The pointer to the alternatively reversed linked list returned from the recursive call is saved to curr->next where curr points to the 2K-th node in list pointed by prev.
- Therefore, prev now points to the final list
3 β 2 β 1 β 4 β 5 β 6 β 8 β 7
- Finally prev pointer is returned.
Approach 2: Iterative Implementation
Algorithm
Step 1: Reverse first k nodes of the linked list.
Step 2: While reversing, we keep track of the first and last node of the reversed linked list using the join and tail pointer.
Step 3: After reversing the k nodes of the linked list, we join the nodes pointed by the tail pointer and join pointer and make tail point to last node of the reversed resultant linked list.
Step 4: Skip reversing the next K nodes as the linked list needs to be alternatively reversed.
Step 4: We repeat this process until all groups of nodes are alternatively reversed.
Pseudocode
reverseKGroupAltIterative(head, k)
curr = head
prev = nullptr
tail = nullptr
finalHead = nullptr
WHILE curr
join = curr
prev = nullptr
count = 0
WHILE count < k and curr
next = curr.next
curr.next = prev
prev = curr
curr = next
count = count + 1
IF NOT finalHead
finalHead = prev
IF tail
tail.next = prev
tail = join
tail.next = curr
count = 0
WHILE count < k AND curr
prev = curr
curr = curr.next
count = count + 1
tail = prev
return finalHead
Implementation
Following is the C++ implementation:
#include <iostream>
using namespace std;
struct Node {
int val;
struct Node *next;
Node(int x): val(x), next(nullptr) {}
};
Node* reverseKGroupAltIterative(Node *head,int k) {
Node *curr = head;
Node *prev = nullptr;
Node *tail = nullptr;
Node *finalHead = nullptr;
while(curr != nullptr) {
// join points to first node in group of k node
// On reversal join points to the last node as order is changed
Node *join = curr;
// Reset the value of prev
prev = nullptr;
int count = 0;
while(count < k && curr != nullptr) {
Node *next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
count++;
}
// finalHead points to main resultant list
if(finalHead == nullptr)
finalHead = prev;
// Join main resultant list and the reversed list
if(tail != nullptr)
tail->next = prev;
// Pointing tail pointer to the new tail node
tail = join;
// Joining the remaining list to be processed with the resultant list
tail->next = curr;
// Next task is to skip next K nodes
count = 0;
while(count < k && curr != nullptr) {
prev = curr;
curr = curr->next;
count++;
}
// Make tail pointer point to the new tail node after skipping K nodes
tail = prev;
}
return finalHead;
}
int main() {
// Creating singly linked list
// 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
struct Node *head = new Node(1);
struct Node *curr = head;
for(int i=2;i<=8;i++) {
curr->next = new Node(i);
curr = curr->next;
}
// Initialize k
int k = 3;
// Reverse first K nodes of linked list
head = reverseKGroupAltIterative(head, k);
// Print list elements
while(head) {
cout<<head->val<<" ";
head = head->next;
}
cout<<endl;
return 0;
}
Explanation
- Consider singly linked list where Node pointer head points to first node in
1 β 2 β 3 β 4 β 5 β 6 β 7 β 8
and let k = 3. - Four Node pointers curr, prev, tail and finalHead are created having values of head, NULL, NULL and NULL.
- During, each iteration of outer loop, we set the value of join and prev to curr and NULL respectively.
- Now, we reverse the first K nodes i.e. 3 nodes of the linked list. We loop through the list as long as count value is less than k and curr is not NULL.
- During each iteration of inner loop, each node is reversed and prev points to the reversed linked list i.e. after first iteration prev points to
1
and curr points to2 β 3 β 4 β 5 β 6 β 7 β 8
, after second iteration prev points to2 β 1
and curr points to3 β 4 β 5 β 6 β 7 β 8
and after third iteration prev points to3 β 2 β 1
and curr points to4 β 5 β 6 β 7 β 8
after which the loop breaks as count is equal to k. - finalHead pointer is used to point to resultant final reversed linked list. For that, during the first iteration of outer loop we point finalHead to the reversed list we get
3 β 2 β 1
. In the successive iterations, we simply append the reversed list obtained at the end of list pointed by finalHead i.e. after second iteration of outer loop finalHead points to3 β 2 β 1 β 4 β 5 β 6
and in the last outer loop iteration finalHead points to3 β 2 β 1 β 4 β 5 β 6 β 8 β 7
. - Next, if the tail is not NULL, we are setting tail.next's value equal to prev and this basically appends the reversed linked list to the reversed resultant linked list pointed by finalHead.
- Next step is to update value tail pointer by setting it to join pointer value which makes tail now point to last node present in resultant linked list. tail.next is set to the value of curr where curr points to the remaining nodes of the linked list to be reversed.
- Now we have to skip next K nodes and this is done by using a while loop and we store the previous node in each step using prev. When curr points to (2K+1)-th node, we breakout of the loop. Now tail pointer's value is set to prev where prev points to 2K-th node. This becomes the new tail node.
- In the end, finalHead points to the final linked list
3 β 2 β 1 β 4 β 5 β 6 β 8 β 7
. - finalHead pointer is returned from the function.
Question 1
What is the space complexity of this algorithm?
Question 2
What is the worst case time complexity of this algorithm?
With this article at OpenGenus, you must have the complete idea of algorithm to reverse alternate groups of K nodes in a Singly Linked List. Enjoy.