Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Data Structure that supports queue like operations and mode finding

This was an interview question asked to me almost 3 years back and I was pondering about this a while back.

Design a data structure that supports the following operations: insert_back(), remove_front() and find_mode(). Best complexity required.

The best solution I could think of was O(logn) for insertion and deletion and O(1) for mode. This is how I solved it: Keep a queue DS for handling which element is inserted and deleted. Also keep an array which is max heap ordered and a hash table. The hashtable contains an integer key and an index into the heap array location of that element. The heap array contains an ordered pair (count,element) and is ordered on the count property.

Insertion : Insert the element into the queue. Find the location of the heap array index from the hashtable. If none exists, then add the element to the heap and heapify upwards. Then add the final location into the hashtable. Increment the count in that location and heapify upwards or downwards as needed to restore the heap property.

Deletion : Remove element from the head of the queue. From the hash table, find a location in the heap array index. Decrement the count in the heap and reheapify upward or downwards as needed to restore the heap property.

Find Mode: The element at the head of the array heap (getMax()) will give us the mode.

Can someone please suggest something better. The only optimization I could think of was using a Fibonacci heap but I am not sure if that is a good fit in this problem.

like image 695
rajaditya_m Avatar asked Apr 27 '26 19:04

rajaditya_m


1 Answers

I think there is a solution with O(1) for all operations.

You need a deque, and two hashtables.

The first one is a linked hashtable, where for each element you store its count, the next element in count order and a previous element in count order. Then you can look the next and previous element's entries in that hashtable in a constant time. For this hashtable you also keep and update the element with the largest count. (element -> count, next_element, previous_element)

In the second hashtable for each distinct number of elements, you store the elements with that count in the start and in the end of the range in the first hashtable. Note that the size of this hashtable will be less than n (it's O(sqrt(n)), I think). (count -> (first_element, last_element))

Basically, when you add an element to or remove an element from the deque, you can find its new position in the first hashtable by analyzing its next and previous elements, and the values for the old and new count in the second hashtable in constant time. You can remove and add elements in the first hashtable in constant time, using algorithms for linked lists. You can also update the second hashtable and the element with the maximum count in constant time as well.

I'll try writing pseudocode if needed, but it seems to be quite complex with many special cases.

like image 187
Kolmar Avatar answered Apr 30 '26 09:04

Kolmar