1. put(U__ID, value): Insert the value in the cache if the key(‘U__ID’) is not already present or update the value of the given key if the key is already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting the new item.
2. get(U__ID): Return the value of the key(‘U__ID’), present in the cache, if it’s present otherwise return -1.
1) The frequency of use of an element is calculated by a number of operations with its ‘U_ID’ performed after it is inserted in the cache.
2) If multiple elements have the least frequency then we remove the element which was least recently used.
Type 1: for put(key, value) operation.
Type 2: for get(key) operation.
We perform the following operations on an empty cache which has capacity 2:
When operation 1 2 3 is performed, the element with 'U_ID' 2 and value 3 is inserted in the cache.
When operation 1 2 1 is performed, the element with 'U_ID' 2’s value is updated to 1.
When operation 2 2 is performed then the value of 'U_ID' 2 is returned i.e. 1.
When operation 2 1 is performed then the value of 'U_ID' 1 is to be returned but it is not present in cache therefore -1 is returned.
When operation 1 1 5 is performed, the element with 'U_ID' 1 and value 5 is inserted in the cache.
When operation 1 6 4 is performed, the cache is full so we need to delete an element. First, we check the number of times each element is used. Element with 'U_ID' 2 is used 3 times (2 times operation of type 1 and 1-time operation of type 1). Element with 'U_ID' 1 is used 1 time (1-time operation of type 1). So element with 'U_ID' 1 is deleted. The element with 'U_ID' 6 and value 4 is inserted in the cache.
The first line contains a single integer ‘T’ representing the number of test cases.
The first line of each test case contains two single space-se[arated integers ‘N’ and ‘M’ representing the size of cache and number of operations respectively.
Next ‘M’ lines contain operations that have to be performed on the cache.
For each test case, print a vector/list that contains answers of all the operations of type 2 and in the order in which they were asked.
1. All the operations are valid.
2. You do not need to print anything; it has already been taken care of. Just implement the function.
1 <= T <= 10
1 <= N <= 1000
1 <= M <= 1000
1 <= U_ID <= 10^3
1 <= VAL<= 10^6
Time Limit: 1sec
In this approach, we will create 2 lists ‘cache’ and ‘nodes’, one for the keys current present in the cache and another list for the information about the key such as frequency, recency and value. Then for each query, we find the key in ‘cache’ and update the value if needed.
We will create a class Node(value, index, freq), where value is the value of the node, index int recency of the node, i.e., how recently it is used, and freq is the frequency of the Node.
In this approach, we create a hash map of ordered maps, where each key in the map will have a set of the node with that frequency. Each time node is fetched or updated, we update the frequency of the node by deleting it from its ordered map and adding it in the ordered map with 1 higher frequency.
We also maintain a minimum frequency, if the cache is full we can delete the first element in the map of minimum frequency, since each map is ordered it will be the first element of the map.
In an ordered map deletion will take logarithmic time.
We create a Node(value) class, where ‘value’ is the value of the node and it also has a frequency property ‘freq’ which is initialized to 1.
We will also create a helper method in the LFUCache class called updateNodeFreq(key), where the key is the key of the node whose frequency is to be updated.
In this approach, we will make a hashmap of all frequencies, but instead of storing the nodes in an ordered map, we will store them in a doubly-linked list. Due to using a doubly-linked list, if we have a reference for a node we can delete it in constant time.
We will create a Node(key, value), where key and value are the respective values in the cache. It also has prev and next, the pointer not next, and previous nodes in the linked list.
We will create a class DoubleLinkedList, which has properties like rootNode a Node object, representing the sentinel node of the linked list. rootNode.prev will point to the last node of the list, while rootNode.next will point to the first node of the list.
We will create a method in LFUCache class updateNodeFreq(node), where node a Node class object whose frequency is to be updated.
In this approach, we will make a hashmap of all frequencies, but instead of storing the nodes in an ordered map, we will store them in a doubly-linked list. Due to using a doubly-linked list, if we have a reference for a node we can delete it in constant time.
We will create a Node(key, value), where key and value are the respective values in the cache. It also has prev and next, the pointer not next, and previous nodes in the linked list.
We will create a class DoubleLinkedList, which has properties like rootNode a Node object, representing the sentinel node of the linked list. rootNode.prev will point to the last node of the list, while rootNode.next will point to the first node of the list.
We will create a method in LFUCache class updateNodeFreq(node), where node a Node class object whose frequency is to be updated.