Remove Duplicates from a Sorted Linked List Using Recursion

A linked list is a sequence of elements that are connected together. Each list have a head and series of nodes and each node has data of the current node and link to next node. The basic operations of a linked list are insertion, deletion, search and delete.

Removing duplicates from a sorted linked list

One way to remove nodes from is using recursion. The idea is to compare each node with its adjacent node and delete the duplicate one they are equal.

Our recursive call will return us to the next node. So for the next element, we will call our recursive function like current_node->next = our_function(node->next).

We trust our recursion that the current_node->next now contains the linked list, which doesn't have any duplicate elements.

In the main method we are biding the list from scratch as −

Node* head = new Node(5);
head->next = new Node(5);
head->next->next = new Node(6);
head->next->next->next = new Node(7);
head->next->next->next->next = new Node(7);
head->next->next->next->next->next = new Node(7); 


The procedure followed by the method to remove duplicates from a sorted linked list using recursion is as follows.

  • Step 1 − A linked list is created with all the values sorted sequentially

  • Step 2 − If the linked list does not exist, the program is terminated.

  • Step 3 − If the linked list does exist, the next value of the head node is compared with the value in the head node. If the two values are the same, the head is deleted.

  • Step 4 − The Step 3 is performed recursively, considering each node as head until the list removes all the duplicate values from itself.

  • Step 5 − The output obtained is a sorted linked list with distinct values


For example, we have a sorted linked list with the following values −


Let us look at a C++ program that will remove duplicates from the above sorted linked list using recursion −

#include <iostream> using namespace std; class Node { public: int data; Node* next; Node(int data) { this->data = data; next = NULL; } }; Node* solve(Node* head) { if (head == NULL) return NULL; head->next = solve(head->next); if (head->next != NULL && head->next->data == head->data) { Node* temp = head->next; delete head; return temp; } return head; } void printList(Node* node) { while (node != NULL) { cout << node->data << (node->next == NULL ? "" : "->"); node = node->next; } } int main() { Node* head = new Node(1); head->next = new Node(1); head->next->next = new Node(1); head->next->next->next = new Node(2); head->next->next->next->next = new Node(3); head->next->next->next->next->next = new Node(3); head->next->next->next->next->next->next = new Node(4); cout << "Linked list before: "; printList(head); head = solve(head); cout << "\nLinked list after: "; printList(head); return 0; }

After this, we check whether or not to include the current node into the linked list. If the satisfied linked list we got from current node->next has the same value as this node, we don't include this; otherwise, we include.

Note − When the current node is NULL, we return our base condition of recursion.


Linked list before: 1->1->1->2->3->3->4
Linked list after: 1->2->3->4


As we see in recursion calls, we trust the next call to achieve the desired result for the rest of the problem. We just solved our current subproblem. Keeping this in mind, we checked whether or not we could include the current element and gave the rest of the linked list to our recursive call and trusted in it to provide us with a valid linked list from then on. The time complexity of our approach is O(n) when we traverse the entire linked list.