Open In App

Design a structure which supports insertion and first non-repeating element in O(1) time

Design a Data structure which supports insertion and first non-repeating element in O(1) time. Operations that are supported by the data structure: 

Note: If there is no non-repeating element in the array then print -1. 

Consider the following custom Data structure:  

Insert(4): [4] 
Insert(1): [4, 1] 
Insert(4): [4, 1, 4]
First_Non_Repeating Element:

The idea is to use Doubly Linked List and a Hash-map to maintain the frequency of the elements of the array. Below is the use-cases of the Hash-map and Doubly-Linked List in this Data-structure: 

Below is the illustration of the operations:  

Advantages of this Data-structure:  

Disadvantages of this Data-structure:  

Below is the implementation of the above approach: 




// C++ implementation of a structure
// which supports insertion, deletion
// and first non-repeating element
// in constant time
 
#include <bits/stdc++.h>
 
using namespace std;
 
// Node for doubly
// linked list
struct node {
     
    // Next pointer
    struct node* next;
     
    // Previous pointer
    struct node* prev;
     
    // Value of node
    int data;
};
 
// Head and tail pointer
// for doubly linked list
struct node *head = NULL, *tail = NULL;
 
// Occurrences map container
// to count for occurrence
// of the element
map<int, int> occurrences;
 
// Address map container
// to store nodes of the
// list which are unique
map<int, node*> address;
 
// Function to insert the element
// into the given data-structure
void insert(int value)
{
    // Increasing count of
    // value to be inserted
    occurrences[value]++;
 
    // If count of element is
    // exactly 1 and is yet
    // not inserted in the list,
    // we insert value in list
    if (occurrences[value] == 1 &&
        address.find(value) == address.end()) {
        struct node* temp =
            (struct node*)malloc(sizeof(struct node));
        temp->next = NULL;
        temp->prev = NULL;
        temp->data = value;
         
        // Storing node mapped
        // to its value in
        // address map container
        address[value] = temp;
         
        // Inserting first element
        if (head == NULL)
        {
            head = temp;
            tail = temp;
        }
        else
        {
            // Appending
            // element at last
            tail->next = temp;
            temp->prev = tail;
            tail = temp;
        }
    }
 
    // if occurrence of particular
    // value becomes >1 and,
    // it is present in address
    // container(which means
    // it is not yet deleted)
    else if (occurrences[value] > 1 &&
        address.find(value) != address.end()) {
              
        // Taking node to be deleted
        struct node* temp = address[value];
         
        // Erasing its value from
        // map to keep track that
        // this element is deleted
        address.erase(value);
 
        // Deleting node in
        // doubly linked list
        if (temp == head) {
            temp = head;
            head = head->next;
            free(temp);
        }
        else if (temp == tail) {
            temp = tail;
            tail->prev->next = NULL;
            free(temp);
        }
        else {
            temp->next->prev = temp->prev;
            temp->prev->next = temp->next;
            free(temp);
        }
    }
}
 
// Function to find the first
// unique element from list
void findUniqueNumber()
{
    // No element in list
    if (head == NULL)
        cout << "-1\n";
         
    // Head node contains
    // unique number
    else
        cout << head->data << "\n";
}
 
 
// Driver Code
int main()
{
    // Inserting element in list
    insert(4);
    insert(1);
    insert(4);
 
    // Finding the first
    // unique number
    findUniqueNumber();
    cout << "\n";
    return 0;
}




// Java implementation of a structure
// which supports insertion, deletion
// and first non-repeating element
// in constant time
 
import java.util.HashMap;
 
// Node for doubly linked list
class Node {
  // Next pointer
  Node next;
 
  // Previous pointer
  Node prev;
 
  // Value of node
  int data;
 
  // Constructor
  Node(int data)
  {
    this.data = data;
    this.next = null;
    this.prev = null;
  }
}
 
public class Main {
  // Head and tail pointers for doubly linked list
  static Node head = null, tail = null;
 
  // Occurrences map container to count for occurrence of
  // the element
  static HashMap<Integer, Integer> occurrences
    = new HashMap<>();
 
  // Address map container to store nodes of the list
  // which are unique
  static HashMap<Integer, Node> address = new HashMap<>();
 
  // Function to insert the element into the given
  // data-structure
  static void insert(int value)
  {
    // Increasing count of value to be inserted
    occurrences.put(
      value, occurrences.getOrDefault(value, 0) + 1);
 
    // If count of element is exactly 1 and is yet not
    // inserted in the list, we insert value in list
    if (occurrences.get(value) == 1
        && !address.containsKey(value)) {
      Node temp = new Node(value);
 
      // Storing node mapped to its value in address
      // map container
      address.put(value, temp);
 
      // Inserting first element
      if (head == null) {
        head = temp;
        tail = temp;
      }
      else {
        // Appending element at last
        tail.next = temp;
        temp.prev = tail;
        tail = temp;
      }
    }
    // If occurrence of particular value becomes >1 and,
    // it is present in address container(which means it
    // is not yet deleted)
    else if (occurrences.get(value) > 1
             && address.containsKey(value)) {
      // Taking node to be deleted
      Node temp = address.get(value);
 
      // Erasing its value from map to keep track that
      // this element is deleted
      address.remove(value);
 
      // Deleting node in doubly linked list
      if (temp == head) {
        head = head.next;
        head.prev = null;
      }
      else if (temp == tail) {
        tail = tail.prev;
        tail.next = null;
      }
      else {
        temp.next.prev = temp.prev;
        temp.prev.next = temp.next;
      }
    }
  }
 
  // Function to find the first unique element from list
  static void findUniqueNumber()
  {
    // No element in list
    if (head == null)
      System.out.println("-1");
    // Head node contains unique number
    else
      System.out.println(head.data);
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    // Inserting element in list
    insert(4);
    insert(1);
    insert(4);
 
    // Finding the first unique number
    findUniqueNumber();
    System.out.println();
  }
}
//  This code is contributed by rutikbhosale




# Python3 implementation of a structure
# which supports insertion, deletion
# and first non-repeating element
# in constant time
  
# Node for doubly
# linked list
class node:
     
    def __init__(self):
         
        # Next pointer
        self.next = None
         
        # Previous pointer
        self.prev = None
         
        # Value of node
        self.data = 0
     
# Head and tail pointer
# for doubly linked list
head = None
tail = None
  
# Occurrences map container
# to count for occurrence
# of the element
occurrences = dict()
  
# Address map container
# to store nodes of the
# list which are unique
address = dict()
  
# Function to insert the element
# into the given data-structure
def insert(value):
     
    global head, tail
     
    # Increasing count of
    # value to be inserted
    if value not in occurrences:
        occurrences[value] = 0
         
    occurrences[value] += 1
     
    # If count of element is
    # exactly 1 and is yet
    # not inserted in the list,
    # we insert value in list
    if (value in occurrences and
     occurrences[value] == 1 and
     value not in address):
        temp = node()
        temp.next = None
        temp.prev = None
        temp.data = value
          
        # Storing node mapped
        # to its value in
        # address map container
        address[value] = temp
          
        # Inserting first element
        if (head == None):
            head = temp
            tail = temp
        else:
             
            # Appending
            # element at last
            tail.next = temp
            temp.prev = tail
            tail = temp
 
    # If occurrence of particular
    # value becomes >1 and,
    # it is present in address
    # container(which means
    # it is not yet deleted)
    elif (value in occurrences and
        occurrences[value] > 1 and
        value in address):
               
        # Taking node to be deleted
        temp = address[value]
          
        # Erasing its value from
        # map to keep track that
        # this element is deleted
        address.pop(value)
  
        # Deleting node in
        # doubly linked list
        if (temp == head):
            temp = head
            head = head.next
            del(temp)
         
        elif (temp == tail):
            temp = tail
            tail.prev.next = None
            del(temp)
         
        else:  
            temp.next.prev = temp.prev
            temp.prev.next = temp.next
            del(temp)
             
# Function to find the first
# unique element from list
def findUniqueNumber():
     
    global head
     
    # No element in list
    if (head == None):
        print(-1)
          
    # Head node contains
    # unique number
    else:
        print(head.data)
         
# Driver Code
if __name__=='__main__':
     
    # Inserting element in list
    insert(4)
    insert(1)
    insert(4)
  
    # Finding the first
    # unique number
    findUniqueNumber()
     
# This code is contributed by rutvik_56




// C# implementation of a structure
// which supports insertion, deletion
// and first non-repeating element
// in constant time
 
using System;
using System.Collections.Generic;
 
// Node for doubly linked list
class Node {
    // Next pointer
    public Node next;
    // Previous pointer
    public Node prev;
 
    // Value of node
    public int data;
 
    // Constructor
    public Node(int data)
    {
        this.data = data;
        this.next = null;
        this.prev = null;
    }
}
 
class MainClass {
    // Head and tail pointers for doubly linked list
    static Node head = null, tail = null;
    // Occurrences map container to count for occurrence of
    // the element
    static Dictionary<int, int> occurrences
        = new Dictionary<int, int>();
 
    // Address map container to store nodes of the list
    // which are unique
    static Dictionary<int, Node> address
        = new Dictionary<int, Node>();
 
    // Function to insert the element into the given
    // data-structure
    static void Insert(int value)
    {
        // Increasing count of value to be inserted
        if (occurrences.ContainsKey(value)) {
            occurrences[value]++;
        }
        else {
            occurrences[value] = 1;
        }
 
        // If count of element is exactly 1 and is yet not
        // inserted in the list, we insert value in list
        if (occurrences[value] == 1
            && !address.ContainsKey(value)) {
            Node temp = new Node(value);
 
            // Storing node mapped to its value in address
            // map container
            address[value] = temp;
 
            // Inserting first element
            if (head == null) {
                head = temp;
                tail = temp;
            }
            else {
                // Appending element at last
                tail.next = temp;
                temp.prev = tail;
                tail = temp;
            }
        }
        // If occurrence of particular value becomes >1 and,
        // it is present in address container(which means it
        // is not yet deleted)
        else if (occurrences[value] > 1
                 && address.ContainsKey(value)) {
            // Taking node to be deleted
            Node temp = address[value];
 
            // Erasing its value from map to keep track that
            // this element is deleted
            address.Remove(value);
 
            // Deleting node in doubly linked list
            if (temp == head) {
                head = head.next;
                head.prev = null;
            }
            else if (temp == tail) {
                tail = tail.prev;
                tail.next = null;
            }
            else {
                temp.next.prev = temp.prev;
                temp.prev.next = temp.next;
            }
        }
    }
 
    // Function to find the first unique element from list
    static void FindUniqueNumber()
    {
        // No element in list
        if (head == null)
            Console.WriteLine("-1");
        // Head node contains unique number
        else
            Console.WriteLine(head.data);
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        // Inserting element in list
        Insert(4);
        Insert(1);
        Insert(4);
 
        // Finding the first unique number
        FindUniqueNumber();
        Console.WriteLine();
    }
}
// This code is contributed by user_dtewbxkn77n




// Node for doubly
// linked list
class Node {
  constructor() {
    // Next pointer
    this.next = null;
    // Previous pointer
    this.prev = null;
    // Value of node
    this.data = 0;
  }
}
 
// Head and tail pointer
// for doubly linked list
let head = null;
let tail = null;
 
// Occurrences map container
// to count for occurrence
// of the element
const occurrences = new Map();
 
// Address map container
// to store nodes of the
// list which are unique
const address = new Map();
 
// Function to insert the element
// into the given data-structure
function insert(value) {
  // Increasing count of
  // value to be inserted
  if (!occurrences.has(value)) {
    occurrences.set(value, 0);
  }
  occurrences.set(value, occurrences.get(value) + 1);
 
  // If count of element is
  // exactly 1 and is yet
  // not inserted in the list,
  // we insert value in list
  if (
    occurrences.has(value) &&
    occurrences.get(value) === 1 &&
    !address.has(value)
  ) {
    const temp = new Node();
    temp.next = null;
    temp.prev = null;
    temp.data = value;
 
    // Storing node mapped
    // to its value in
    // address map container
    address.set(value, temp);
 
    // Inserting first element
    if (head === null) {
      head = temp;
      tail = temp;
    } else {
      // Appending
      // element at last
      tail.next = temp;
      temp.prev = tail;
      tail = temp;
    }
  }
 
  // If occurrence of particular
  // value becomes >1 and,
  // it is present in address
  // container(which means
  // it is not yet deleted)
  else if (
    occurrences.has(value) &&
    occurrences.get(value) > 1 &&
    address.has(value)
  ) {
    // Taking node to be deleted
    const temp = address.get(value);
 
    // Erasing its value from
    // map to keep track that
    // this element is deleted
    address.delete(value);
 
    // Deleting node in
    // doubly linked list
    if (temp === head) {
      head = head.next;
      head.prev = null;
      temp.next = null;
      temp.prev = null;
    } else if (temp === tail) {
      tail = tail.prev;
      tail.next = null;
      temp.next = null;
      temp.prev = null;
    } else {
      temp.prev.next = temp.next;
      temp.next.prev = temp.prev;
      temp.next = null;
      temp.prev = null;
    }
  }
}
 
// Function to find the first
// unique element from list
function findUniqueNumber() {
  // No element in list
  if (head === null) {
    console.log(-1);
  } else {
    // Head node contains
    // unique number
    console.log(head.data);
  }
}
 
// Driver Code
// Inserting element in list
insert(4);
insert(1);
insert(4);
 
// Finding the first
// unique number
findUniqueNumber();
 
// Contributed by adityasharmadev01

Output: 
1

 

Time Complexity: O(1) for insertion and deletion operations
Auxiliary Space: O(n), where n is the number of unique elements 


Article Tags :