Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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_Occurrence(
    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_Occurrence(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_Occurrence(
    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_Occurrence(head);
 
    // Function Call
    print_Linked_List(head);
 
}
}
 
// This code is contributed by shikhasingrajput


Python3




# Python program for the above approach
 
# Node class
class Node:
    def __init__(self, data):
        self.data = data;
        self.next = None;
 
# Function to reverse a Linked List
def reverseList(head):
    prev = None;
    nextNode = None;
    while (head != None):
        # 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
def Remove_Dup_Keep_Last_Occurrence(head):
    # Make a dummy Node
    dummy = Node(-1);
    dummy.next = head;
 
    # Reverse the given Linked List
    dummy.next = reverseList(dummy.next);
 
    # Stores duplicate elements
    visited =set();
    currNode = dummy;
    nextNode = None;
 
    # Iterate over the list
    while (currNode != None and currNode.next != None):
 
        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
            duplicate = nextNode;
            currNode.next = nextNode.next;
 
            # Erase memory of duplicate pointer
            duplicate = None;
        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
def print_Linked_List(head):
    curr = head;
    while (curr != None):
        print(curr.data, end=" ");
        curr = curr.next;
 
# Driver Code
if __name__ == '__main__':
    # Given Input
    head = Node(3);
    head.next = Node(2);
    head.next.next = Node(3);
    head.next.next.next = Node(1);
    head.next.next.next.next = Node(5);
    head.next.next.next.next.next = Node(1);
    head.next.next.next.next.next.next = Node(6);
 
    head = Remove_Dup_Keep_Last_Occurrence(head);
 
    # Function Call
    print_Linked_List(head);
 
# This code is contributed by shikhasingrajput


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
 
    // Node class
public    class Node {
    public    int data;
    public    Node next;
 
    public    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_Occurrence(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<int> visited = new HashSet<int>();
 
        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) {
            Console.Write(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_Occurrence(head);
 
        // Function Call
        print_Linked_List(head);
 
    }
}
 
// This code is contributed by umadevi9616


Javascript




<script>
// javascript program for the above approach
 
    // Node class
class Node {
    constructor(val) {
        this.data = val;
        this.next = null;
    }
}
 
    // Function to reverse a Linked List
    function reverseList(head) {
    var 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
    function Remove_Dup_Keep_Last_Occurrence(head)
    {
     
        // Make a dummy node
        var dummy = new Node(-1);
        dummy.next = head;
 
        // Reverse the given Linked List
        dummy.next = reverseList(dummy.next);
 
        // Stores duplicate elements
        var visited = new Set();
 
        var currNode = dummy;
        var 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.has(nextNode.data)) {
 
                // Stores the duplicate pointer
                var 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
    function print_Linked_List(head) {
var curr = head;
        while (curr != null) {
            document.write(curr.data + " ");
            curr = curr.next;
        }
    }
 
    // Driver Code
     
 
        // Given Input
var 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_Occurrence(head);
 
        // Function Call
        print_Linked_List(head);
 
// This code contributed by umadevi9616
</script>


Output: 

2 3 5 1 6

 

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



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