Lfu Cache

Explanation

To solve this coding challenge, we need to implement a Least Frequently Used (LFU) cache. An LFU cache evicts the least frequently used items when the cache reaches its capacity. If there is a tie (multiple keys with the same frequency), the least recently used key will be evicted first. The main challenge here is to maintain quick (average O(1) time complexity) access and update operations, which requires efficient data structures to keep track of both the access frequency and the recency of each element.
Key Concepts:
  1. Capacity Constraint : The cache should only store up to a specified number of items.
  2. Frequency Tracking : Each key in the cache has an associated frequency which increments every time the key is accessed or updated.
  3. Least Recently Used : If multiple keys have the same frequency, the key that was least recently accessed should be evicted first.
  4. O(1) Operations : Both
    get
    and
    put
    operations need to have an average time complexity of O(1).
  5. Data Structures:
  6. Cache Dictionary : This maps keys to their values and their current frequency.
  7. Frequency Map : A dictionary where the keys are frequencies, and the values are sets containing all keys that have the same frequency. This helps quickly find the least frequently used keys and manage ties effectively.
  8. Recency Tracking : The order within each frequency set will help break ties based on recency.
  9. Procedures:
  10. Initialization (
    __init__
    )
    : Set up the capacity, cache dictionary, and frequency map.
  11. Get Operation (
    get
    )
    : Check if the key exists. If it does, update its frequency and recency, then return its value.
  12. Put Operation (
    put
    )
    : Update the value and frequency of an existing key, or insert a new key. If the cache exceeds capacity, find and remove the least frequently and least recently used key.
  13. Detailed Steps in Pseudocode

  14. Initialize LFU Cache :
    • Initialize with a capacity.
    • Create an empty cache dictionary and a frequency map.
                                                
    Function LFUCache(capacity):
    Initialize cache as an empty dictionary
    Initialize freq_map as an empty dictionary
    Initialize min_freq as 0
    Set the given capacity
    EndFunction
    
                                            
  15. Get Value :
    • Check if the key exists in the cache.
    • Fetch the value and frequency.
    • Increment the frequency.
    • Update the frequency map.
    • Return the value if found, otherwise return -1.
                                                
    Function get(key):
    If key is not in cache:
    Return -1
    Else:
    (value, frequency) = cache[key]
    Increment frequency
    Remove key from freq_map[frequency]
    If freq_map[frequency] is empty:
    Remove freq_map[frequency]
    If min_freq equals frequency:
    Increment min_freq
    Add key to freq_map[frequency + 1]
    Update cache[key] to (value, frequency + 1)
    Return value
    EndFunction
    
                                            
  16. Put Value :
    • If the capacity is 0, do nothing.
    • If the key exists, update the value and frequency.
    • If the key doesn’t exist, handle the insertion:
      • If the cache is at capacity, evict the least frequently and least recently used key.
      • Insert the new key with a frequency of 1.
                                            
Function put(key, value):
    If cache capacity is 0:
        Return
    If key is in cache:
        (old_value, frequency) = cache[key]
        Update cache[key] to (value, frequency + 1)
        Remove key from freq_map[frequency]
        If freq_map[frequency] is empty:
            Remove freq_map[frequency]
            If min_freq equals frequency:
                Increment min_freq
        Add key to freq_map[frequency + 1]
    Else:
        If cache is at capacity:
            Least_frequency = min_freq
            Remove least_recent_key from freq_map[Least_frequency]
            If freq_map[Least_frequency] is empty:
                Remove freq_map[Least_frequency]
            Remove least_recent_key from cache
        Add key to cache with value and frequency 1
        Add key to freq_map[1]
        Set min_freq to 1
EndFunction

                                        
In this way, the LFU cache manages both space and time efficiency by using appropriate data structures and algorithms. The above steps detail every aspect of the LFU Cache's operations, ensuring all edge cases and constraints are handled properly.