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 -> 1Input: 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++ 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 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 |
# 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# 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 |
<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> |
2 3 5 1 6
Time Complexity: O(N)
Auxiliary Space: O(N)