What is LFU cache?
LFU (Least Frequently Used) Cache is a type of caching algorithm where the items that have been used least frequently are removed first when the cache reaches its limit.
How to implement it?
A basic LFU Cache requires the following data structures:
- A Hash Map to store key-value pairs in the cache.
- A linked list to maintain the frequency of each item.
- A Hash Map to store ref to the linked list node for each key.
Implementation in Kotlin
package leetcode.datastructures
class LFUCache(private val capacity: Int) {
class Node(val key: Int, var value: Int) {
var frequency: Int = 1
var prev: Node? = null
var next: Node? = null
}
class DoublyLinkedList {
var head = Node(0, 0)
var tail = Node(0, 0)
init {
tail.prev = head
head.next = tail
}
fun addNode(node: Node) {
node.next = tail
node.prev = tail.prev
tail.prev?.next = node
tail.prev = node
}
fun removeNode(node: Node) {
node.prev?.next = node.next
node.next?.prev = node.prev
}
}
private val cache = mutableMapOf<Int, Node>()
private val frequencyMap = mutableMapOf<Int, DoublyLinkedList>()
private var minFrequency = 0
fun get(key: Int): Int {
if (!cache.containsKey(key)) return -1
val node = cache[key]!!
update(node)
return node.value
}
fun put(key: Int, value: Int) {
if (capacity <= 0) return
if (cache.containsKey(key)) {
val node = cache[key]!!
node.value = value
update(node)
return
} else {
if (cache.size == capacity) {
val node = frequencyMap[minFrequency]!!.head.next!!
frequencyMap[minFrequency]!!.removeNode(node)
cache.remove(node.key)
}
val newNode = Node(key, value)
cache[key] = newNode
if (!frequencyMap.containsKey(newNode.frequency)) {
frequencyMap[newNode.frequency] = DoublyLinkedList()
}
frequencyMap[newNode.frequency]!!.addNode(newNode)
minFrequency = 1
}
}
private fun update(node: Node) {
val frequency = node.frequency
node.frequency++
val keys = frequencyMap[frequency]!!
keys.removeNode(node)
if (minFrequency == frequency && keys.head.next == keys.tail) {
minFrequency++
}
if (!frequencyMap.containsKey(frequency + 1)) {
frequencyMap[frequency + 1] = DoublyLinkedList()
}
frequencyMap[frequency + 1]!!.addNode(node)
}
}Complexity Analysis
put- O(1)get- O(1)
Space complexity: O(n)