Skip to content
Related Articles

Related Articles

Improve Article

Modify a Linked List to contain last occurrences of every duplicate element

  • Last Updated : 20 Aug, 2021

Given an unsorted Singly Linked List consisting of N nodes that may contain duplicate elements, the task is to remove all but the last occurrence of duplicate elements from the Linked List.

Examples:

Input: 1 -> 2 -> 7 -> 3 -> 2 -> 5 -> 1
Output: 7 -> 3 -> 2 -> 5 -> 1
Explanation: 
Given Linked List: 1 -> 2 -> 7 -> 3 -> 2 -> 5 -> 1
Duplicate elements: 1, 2
Modified Linked List: 7 -> 3 -> 2 -> 5 -> 1

Input: 1 -> 2 -> 3 -> 4 -> 5
Output: 1 -> 2 -> 3 -> 4 -> 5

Approach: Follow the steps below to solve the problem:



  • Initialize a dummy node and make it’s next point to head.
  • Reverse the given Linked List.
  • Initialize an unordered set, say visited, to store the already visited nodes.
  • Initialize two nodes, say currnode, pointing to the dummy node, and nextnode, to store the next node of the current node.
  • Iterate over the linked list and check if data of the next node of the current node is already visited or not.
  • If it is already visited, then perform the following steps:
    • Initialize a new node, say duplicate, to store the nextnode which is a duplicate node in this case.
    • Make current’s next point to next of the nextnode.
  • Otherwise:
    • Insert the data of nextnode into the visited set.
    • Make nextnode as currentnode.
  • Finally, reverse the modified linked list and return.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Node class
class Node {
public:
    int data;
    Node* next;
 
    Node(int x)
    {
        this->data = x;
        this->next = NULL;
    }
};
 
// Function to reverse a Linked List
Node* reverseList(Node* head)
{
    Node *prev = NULL, *nextNode = NULL;
    while (head != NULL) {
 
        // Point to next node
        // of the current node
        nextNode = head->next;
 
        // Point next of current
        // to the previous node
        head->next = prev;
 
        prev = head;
 
        head = nextNode;
    }
    return prev;
}
 
// Function to modify a linked list
// such that it contains only the
// last occurrence of duplicate elements
Node* Remove_Dup_Keep_Last_Occurence(
    Node* head)
{
    // Make a dummy node
    Node* dummy = new Node(-1);
    dummy->next = head;
 
    // Reverse the given Linked List
    dummy->next = reverseList(dummy->next);
 
    // Stores duplicate elements
    unordered_set<int> visited;
 
    Node *currNode = dummy, *nextNode;
 
    // Iterate over the list
    while (currNode != NULL
           && currNode->next != NULL) {
 
        nextNode = currNode->next;
 
        // Check if data of the next node of the
        // current node is already visited or not
        if (visited.count(nextNode->data) != 0) {
 
            // Stores the duplicate pointer
            Node* duplicate = nextNode;
            currNode->next = nextNode->next;
 
            // Erase memory of duplicate pointer
            delete duplicate;
        }
        else {
 
            // Mark as visited to data of nextNode
            visited.insert(nextNode->data);
 
            // Go for the next node
            currNode = nextNode;
        }
    }
 
    // Reverse the modified linked list
    dummy->next = reverseList(dummy->next);
 
    return dummy->next;
}
 
// Function to print a Linked List
void print_Linked_List(Node* head)
{
    Node* curr = head;
    while (curr != NULL) {
        cout << curr->data << ' ';
        curr = curr->next;
    }
}
 
// Driver Code
int main()
{
 
    // Given Input
    Node* head = new Node(3);
    head->next = new Node(2);
    head->next->next = new Node(3);
    head->next->next->next = new Node(1);
    head->next->next->next->next = new Node(5);
    head->next->next->next->next->next = new Node(1);
    head->next->next->next->next->next->next = new Node(6);
 
    head = Remove_Dup_Keep_Last_Occurence(head);
 
    // Function Call
    print_Linked_List(head);
 
    return 0;
}

Java




// Java program for the above approach
import java.util.*;
 
class GFG
{
 
// Node class
static class Node {
    int data;
    Node next;
 
    Node(int x)
    {
        this.data = x;
        this.next = null;
    }
};
 
// Function to reverse a Linked List
static Node reverseList(Node head)
{
    Node prev = null, nextNode = null;
    while (head != null) {
 
        // Point to next node
        // of the current node
        nextNode = head.next;
 
        // Point next of current
        // to the previous node
        head.next = prev;
 
        prev = head;
 
        head = nextNode;
    }
    return prev;
}
 
// Function to modify a linked list
// such that it contains only the
// last occurrence of duplicate elements
static Node Remove_Dup_Keep_Last_Occurence(
    Node head)
{
    // Make a dummy node
    Node dummy = new Node(-1);
    dummy.next = head;
 
    // Reverse the given Linked List
    dummy.next = reverseList(dummy.next);
 
    // Stores duplicate elements
    HashSet<Integer> visited = new HashSet<Integer>();
 
    Node currNode = dummy;
    Node nextNode;
 
    // Iterate over the list
    while (currNode != null
           && currNode.next != null) {
 
        nextNode = currNode.next;
 
        // Check if data of the next node of the
        // current node is already visited or not
        if (visited.contains(nextNode.data)) {
 
            // Stores the duplicate pointer
            Node duplicate = nextNode;
            currNode.next = nextNode.next;
 
            // Erase memory of duplicate pointer
            duplicate=null;
        }
        else {
 
            // Mark as visited to data of nextNode
            visited.add(nextNode.data);
 
            // Go for the next node
            currNode = nextNode;
        }
    }
 
    // Reverse the modified linked list
    dummy.next = reverseList(dummy.next);
 
    return dummy.next;
}
 
// Function to print a Linked List
static void print_Linked_List(Node head)
{
    Node curr = head;
    while (curr != null) {
        System.out.print(curr.data +" ");
        curr = curr.next;
    }
}
 
// Driver Code
public static void main(String[] args)
{
 
    // Given Input
    Node head = new Node(3);
    head.next = new Node(2);
    head.next.next = new Node(3);
    head.next.next.next = new Node(1);
    head.next.next.next.next = new Node(5);
    head.next.next.next.next.next = new Node(1);
    head.next.next.next.next.next.next = new Node(6);
 
    head = Remove_Dup_Keep_Last_Occurence(head);
 
    // Function Call
    print_Linked_List(head);
 
}
}
 
// This code is contributed by shikhasingrajput

 
 

Output: 
2 3 5 1 6

 

 

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

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :