Least Frequently Used (LFU) Cache Implementation
Last Updated :
11 Jul, 2025
Design a data structure for the Least Frequently Used (LFU) Cache.
LFU (Least Frequently Used) Cache is a caching algorithm where the least frequently accessed cache block is removed when the cache reaches its capacity. In LFU, we take into account how often a page is accessed and how recently it was accessed. If a page has a higher frequency than another, it cannot be removed, as it is accessed more frequently if multiple pages share the same frequency, the one that was accessed least recently (the Least Recently Used, or LRU page) is removed. This is typically handled using a FIFO (First-In-First-Out) method, where the oldest page among those with the same frequency is the one to be removed.
It should support the following operations:
- LFUCache (Capacity c): Initialize LFU cache with positive size capacity c.
- get(key) - Returns the value of the given key if it exists in the cache; otherwise, returns -1.
- put(key, value) - Inserts or updates the key-value pair in the cache. If the cache reaches capacity, remove the least frequently used item before adding the new item. If there is a tie between keys with the same frequency, the least recently used (LRU) key among them should be removed.
Example:
Input: [LFUCache cache = new LFUCache(2), put(1, 1) , put(2, 2) , get(1) , put(3, 3) , get(2), put(4, 4), get(3) , get(4), put(5, 5)]
Output: [1 , -1, -1, 4]
Explanation: The values mentioned in the output are the values returned by get operations.
- Initialize LFUCache class with capacity = 2.
- cache.put(1, 1): (key, pair) = (1, 1) inserts the key-value pair (1, 1).
- cache.put(2, 2): (key , pair) = (2, 2) inserts the key-value pair (2, 2).
- cache.get(1): The cache retrieves the value for key 1, which is 1. After accessing key 1, its frequency increases to 2.
- cache.put(3, 3): The cache is now full (capacity = 2). To insert the new key-value pair (3, 3), the least frequently used key must be removed. key 2 have a frequency of 1. As a result, key 2 (the least recently accessed key) is removed and key-value pair (3, 3) is inserted with frequency 1.
- cache.get(2): cache returns -1 indicating that key 2 is not found.
- cache.put(4, 4): key 3 is removed as it has frequency of 1 and key-value pair (4, 4) is inserted with frequency 1.
- cache.get(3): returns -1 (key 3 not found)
- cache.get(4):The cache retrieves the value for key 4, which is 4. After accessing key 4, its frequency increases to 2.
- cache.put(5, 5): key 1 and key 4 both have a frequency of 2 . Now, key 1 will be removed as key 4 is most recently used and key-value pair (5, 5) is inserted with frequency 1.
[Naive Approach - 1] Using an Array of Nodes
The idea is to implement LFU using an array to store nodes, where each node holds a key-value pair, frequency count and timestamp. The primary operations, get and put, are performed with linear time due to the need to search through the array. The size of the array will be equal to the given capacity of the cache.
- put(int key, int value)
- If the cache is full, find the node with the least frequency and replace this node with the new key and value. When there is a tie (i.e., two or more keys with the same frequency), the least recently used key would be replaced.
- else, simply add the new node to the end of the array with the timestamp of insertion and frequency value 1.
- Time Complexity: O(n) (because we might have to search for the least frequent node).
- get(int key)
- Search through the array for the node with the matching key.
- If found, update its timestamp and frequency and return its value , else return -1.
- Time Complexity: O(n) (because we might have to check every node).
We initialize an array of size equal to that of our cache. Here each data element stores extra information to mark with an access timestamp and frequency. Timestamp shows the time at which the key is stored and frequency is count of number of time the key is used. We will use frequency to find the least frequently used element and the timestamp to find out the least recently used element in case of tie between frequency of multiple elements.
C++
// C++ Program to implement LFU Cache
// using array
#include <bits/stdc++.h>
using namespace std;
struct Node {
int key, value;
int timeStamp, cnt;
Node(int key, int val, int timeStamp) {
this->key = key;
this->value = val;
this->cnt = 1;
this->timeStamp = timeStamp;
}
};
class LFUCache {
public:
int capacity;
int curSize;
int curTime;
vector<Node *> cacheList;
// Constructor to initialize values
LFUCache(int capacity) {
this->capacity = capacity;
curSize = 0;
curTime = 0;
cacheList.resize(capacity, nullptr);
}
// Function to get the key's value
int get(int key) {
curTime++;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] != nullptr && cacheList[i]->key == key) {
cacheList[i]->cnt++;
cacheList[i]->timeStamp = curTime;
return cacheList[i]->value;
}
}
return -1;
}
// Function to put a key-value pair
void put(int key, int value) {
curTime++;
if (capacity == 0)
return;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] != nullptr && cacheList[i]->key == key) {
cacheList[i]->value = value;
cacheList[i]->cnt++;
cacheList[i]->timeStamp = curTime;
return;
}
}
if (curSize < capacity) {
curSize++;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] == nullptr) {
cacheList[i] = new Node(key, value, curTime);
return;
}
}
}
else {
int minCnt = INT_MAX, minTime = INT_MAX, minIndex = -1;
for (int i = 0; i < capacity; i++) {
if (cacheList[i]->cnt < minCnt ||
(cacheList[i]->cnt == minCnt && cacheList[i]->timeStamp < minTime)) {
minCnt = cacheList[i]->cnt;
minTime = cacheList[i]->timeStamp;
minIndex = i;
}
}
cacheList[minIndex] = new Node(key, value, curTime);
}
}
};
int main() {
LFUCache cache(2);
cache.put(1, 1);
cache.put(2, 2);
cout << cache.get(1) << " ";
cache.put(3, 3);
cout << cache.get(2) << " ";
cache.put(4, 4);
cout << cache.get(3) << " ";
cout << cache.get(4) << " ";
cache.put(5, 5);
return 0;
}
Java
// Java Program to implement LFU Cache
// using array
import java.util.*;
class Node {
int key, value;
int timeStamp, cnt;
Node(int key, int val, int timeStamp) {
this.key = key;
this.value = val;
this.cnt = 1;
this.timeStamp = timeStamp;
}
}
class LFUCache {
int capacity;
int curSize;
int curTime;
Node[] cacheList;
// Constructor to initialize values
LFUCache(int capacity) {
this.capacity = capacity;
curSize = 0;
curTime = 0;
cacheList = new Node[capacity];
}
// Function to get the key's value
int get(int key) {
curTime++;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] != null
&& cacheList[i].key == key) {
cacheList[i].cnt++;
cacheList[i].timeStamp = curTime;
return cacheList[i].value;
}
}
return -1;
}
// Function to put a key-value pair
void put(int key, int value) {
curTime++;
if (capacity == 0)
return;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] != null
&& cacheList[i].key == key) {
cacheList[i].value = value;
cacheList[i].cnt++;
cacheList[i].timeStamp = curTime;
return;
}
}
if (curSize < capacity) {
curSize++;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] == null) {
cacheList[i]
= new Node(key, value, curTime);
return;
}
}
}
else {
int minCnt = Integer.MAX_VALUE;
int minTime = Integer.MAX_VALUE;
int minIndex = -1;
for (int i = 0; i < capacity; i++) {
if (cacheList[i].cnt < minCnt
|| (cacheList[i].cnt == minCnt
&& cacheList[i].timeStamp
< minTime)) {
minCnt = cacheList[i].cnt;
minTime = cacheList[i].timeStamp;
minIndex = i;
}
}
cacheList[minIndex]
= new Node(key, value, curTime);
}
}
}
class GfG {
public static void main(String[] args) {
LFUCache cache = new LFUCache(2);
cache.put(1, 1);
cache.put(2, 2);
System.out.print(cache.get(1) + " ");
cache.put(3, 3);
System.out.print(cache.get(2) + " ");
cache.put(4, 4);
System.out.print(cache.get(3) + " ");
System.out.print(cache.get(4) + " ");
cache.put(5, 5);
}
}
Python
# Python Program to implement LFU Cache
# using array
class Node:
def __init__(self, key, value, timeStamp):
self.key = key
self.value = value
self.cnt = 1
self.timeStamp = timeStamp
# LFU Cache class
class LFUCache:
# Constructor to initialize values
def __init__(self, capacity):
self.capacity = capacity
self.curSize = 0
self.curTime = 0
self.cacheList = [None] * capacity
# Function to get the key's value
def get(self, key):
self.curTime += 1
for i in range(self.capacity):
if self.cacheList[i] is not None and self.cacheList[i].key == key:
self.cacheList[i].cnt += 1
self.cacheList[i].timeStamp = self.curTime
return self.cacheList[i].value
return -1
# Function to put a key-value pair
def put(self, key, value):
self.curTime += 1
if self.capacity == 0:
return
for i in range(self.capacity):
if self.cacheList[i] is not None and self.cacheList[i].key == key:
self.cacheList[i].value = value
self.cacheList[i].cnt += 1
self.cacheList[i].timeStamp = self.curTime
return
if self.curSize < self.capacity:
self.curSize += 1
for i in range(self.capacity):
if self.cacheList[i] is None:
self.cacheList[i] = Node(key, value, self.curTime)
return
else:
minCnt = float('inf')
minTime = float('inf')
minIndex = -1
for i in range(self.capacity):
if self.cacheList[i].cnt < minCnt or (
self.cacheList[i].cnt == minCnt and self.cacheList[i].timeStamp < minTime
):
minCnt = self.cacheList[i].cnt
minTime = self.cacheList[i].timeStamp
minIndex = i
self.cacheList[minIndex] = Node(key, value, self.curTime)
if __name__ == "__main__":
cache = LFUCache(2)
cache.put(1, 1)
cache.put(2, 2)
print(cache.get(1), end=" ")
cache.put(3, 3)
print(cache.get(2), end=" ")
cache.put(4, 4)
print(cache.get(3), end=" ")
print(cache.get(4), end=" ")
cache.put(5, 5)
C#
// C# Program to implement LFU Cache
// using array
using System;
class Node {
public int key, value, timeStamp, cnt;
public Node(int key, int value, int timeStamp) {
this.key = key;
this.value = value;
this.cnt = 1;
this.timeStamp = timeStamp;
}
}
// LFU Cache class
class LFUCache {
private int capacity;
private int curSize;
private int curTime;
private Node[] cacheList;
// Constructor to initialize values
public LFUCache(int capacity) {
this.capacity = capacity;
curSize = 0;
curTime = 0;
cacheList = new Node[capacity];
}
// Function to get the key's value
public int Get(int key) {
curTime++;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] != null &&
cacheList[i].key == key) {
cacheList[i].cnt++;
cacheList[i].timeStamp = curTime;
return cacheList[i].value;
}
}
return -1;
}
// Function to put a key-value pair
public void Put(int key, int value) {
curTime++;
if (capacity == 0) return;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] != null &&
cacheList[i].key == key) {
cacheList[i].value = value;
cacheList[i].cnt++;
cacheList[i].timeStamp = curTime;
return;
}
}
if (curSize < capacity) {
curSize++;
for (int i = 0; i < capacity; i++) {
if (cacheList[i] == null) {
cacheList[i] = new Node(key, value, curTime);
return;
}
}
} else {
int minCnt = int.MaxValue;
int minTime = int.MaxValue;
int minIndex = -1;
for (int i = 0; i < capacity; i++) {
if (cacheList[i].cnt < minCnt ||
(cacheList[i].cnt == minCnt &&
cacheList[i].timeStamp < minTime)) {
minCnt = cacheList[i].cnt;
minTime = cacheList[i].timeStamp;
minIndex = i;
}
}
cacheList[minIndex] = new Node(key, value, curTime);
}
}
}
class GfG {
static void Main() {
LFUCache cache = new LFUCache(2);
cache.Put(1, 1);
cache.Put(2, 2);
Console.Write(cache.Get(1) + " ");
cache.Put(3, 3);
Console.Write(cache.Get(2) + " ");
cache.Put(4, 4);
Console.Write(cache.Get(3) + " ");
Console.Write(cache.Get(4) + " ");
cache.Put(5, 5);
}
}
JavaScript
// JavaScript Program to implement LFU Cache
// using array
class Node {
constructor(key, value, timeStamp) {
this.key = key;
this.value = value;
this.cnt = 1;
this.timeStamp = timeStamp;
}
}
// LFU Cache class
class LFUCache {
// Constructor to initialize values
constructor(capacity) {
this.capacity = capacity;
this.curSize = 0;
this.curTime = 0;
this.cacheList = new Array(capacity).fill(null);
}
// Function to get the key's value
get(key) {
this.curTime++;
for (let i = 0; i < this.capacity; i++) {
if (this.cacheList[i] !== null &&
this.cacheList[i].key === key) {
this.cacheList[i].cnt++;
this.cacheList[i].timeStamp = this.curTime;
return this.cacheList[i].value;
}
}
return -1;
}
// Function to put a key-value pair
put(key, value) {
this.curTime++;
if (this.capacity === 0) return;
for (let i = 0; i < this.capacity; i++) {
if (this.cacheList[i] !== null &&
this.cacheList[i].key === key) {
this.cacheList[i].value = value;
this.cacheList[i].cnt++;
this.cacheList[i].timeStamp = this.curTime;
return;
}
}
if (this.curSize < this.capacity) {
this.curSize++;
for (let i = 0; i < this.capacity; i++) {
if (this.cacheList[i] === null) {
this.cacheList[i] = new Node(key, value, this.curTime);
return;
}
}
} else {
let minCnt = Infinity, minTime = Infinity, minIndex = -1;
for (let i = 0; i < this.capacity; i++) {
if (
this.cacheList[i].cnt < minCnt ||
(this.cacheList[i].cnt === minCnt &&
this.cacheList[i].timeStamp < minTime)
) {
minCnt = this.cacheList[i].cnt;
minTime = this.cacheList[i].timeStamp;
minIndex = i;
}
}
this.cacheList[minIndex] = new Node(key, value, this.curTime);
}
}
}
const cache = new LFUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log(cache.get(1) + " ");
cache.put(3, 3);
console.log(cache.get(2) + " ");
cache.put(4, 4);
console.log(cache.get(3) + " ");
console.log(cache.get(4) + " ");
cache.put(5, 5);
Time Complexity: O(n), for each get() and put() operations where n is capacity of cache.
Auxiliary Space: O(capacity)
[Naive Approach - 2] Using Singly Linked List
The approach to implement an LFU (Least Frequently Used) cache involves using a singly linked list to maintain the order of cache entries.
- get(int key): The cache searches for the node with the requested key by traversing the list from the head. If the key is found, update its timestamp and frequency and return its value , else return -1. This operation has a time complexity of O(n) because it may require scanning through the entire list.
- put(int key, int value): The cache inserts a new key-value pair at the end of the list if the cache has not reached its capacity. If the key already exists, the corresponding node is found and updated. When the cache reaches its capacity, the least frequently used element, is removed. When there is a tie (i.e., two or more keys with the same frequency), the least recently used node would be removed. The time complexity for this operation is also O(n) due to the traversal and reordering steps involved.
C++
// C++ Program to implement LFU Cache
// using singly linked list
#include<bits/stdc++.h>
using namespace std;
struct Node {
int key, value;
int timeStamp, cnt;
Node *next;
Node(int key, int val, int timeStamp) {
this->key = key;
this->value = val;
this->cnt = 1;
this->timeStamp = timeStamp;
this->next = nullptr;
}
};
//LFU Cache class
class LFUCache {
public:
int capacity;
int curSize;
int curTime;
Node* head;
// Constructor to initialize values
LFUCache(int capacity) {
this->capacity = capacity;
curSize = 0;
curTime = 0;
head = new Node(-1, -1, -1);
}
// Function to get the key's value
int get(int key) {
curTime++;
Node* temp = head;
while(temp->next != nullptr) {
if(temp->next->key == key) {
temp->next->cnt++;
temp->next->timeStamp = curTime;
return temp->next->value;
}
temp = temp->next;
}
return -1;
}
// Function to put a key-value pair
void put(int key, int value) {
curTime++;
if(capacity == 0) return;
Node* temp = head;
while(temp->next != nullptr) {
if(temp->next->key == key) {
temp->next->value = value;
temp->next->cnt++;
temp->next->timeStamp = curTime;
return;
}
temp = temp->next;
}
if(curSize < capacity) {
curSize++;
Node* temp = head;
while(temp->next != nullptr) {
temp = temp->next;
}
temp->next = new Node(key, value, curTime);
return;
}
else {
int minCnt = INT_MAX, minTime = INT_MAX;
Node* minNode = nullptr;
Node* temp = head;
while(temp->next != nullptr) {
if(temp->next->cnt < minCnt ||
(temp->next->cnt == minCnt &&
temp->next->timeStamp < minTime)) {
minCnt = temp->next->cnt;
minTime = temp->next->timeStamp;
minNode = temp;
}
temp = temp->next;
}
Node* delNode = minNode->next;
minNode->next = minNode->next->next;
delete delNode;
temp = head;
while(temp->next != nullptr) {
temp = temp->next;
}
temp->next = new Node(key, value, curTime);
}
}
};
int main(){
LFUCache cache(2);
cache.put(1, 1);
cache.put(2, 2);
cout << cache.get(1) << " ";
cache.put(3, 3);
cout << cache.get(2) << " ";
cache.put(4, 4);
cout << cache.get(3) << " ";
cout << cache.get(4) << " ";
cache.put(5, 5);
return 0;
}
Java
// Java Program to implement LFU Cache
// using singly linked list
import java.util.*;
class Node {
int key, value;
int timeStamp, cnt;
Node next;
Node(int key, int val, int timeStamp) {
this.key = key;
this.value = val;
this.cnt = 1;
this.timeStamp = timeStamp;
this.next = null;
}
}
class LFUCache {
int capacity;
int curSize;
int curTime;
Node head;
// Constructor to initialize values
LFUCache(int capacity) {
this.capacity = capacity;
curSize = 0;
curTime = 0;
head = new Node(-1, -1, -1);
}
// Function to get the key's value
int get(int key) {
curTime++;
Node temp = head;
while(temp.next != null) {
if(temp.next.key == key) {
temp.next.cnt++;
temp.next.timeStamp = curTime;
return temp.next.value;
}
temp = temp.next;
}
return -1;
}
// Function to put a key-value pair
void put(int key, int value) {
curTime++;
if(capacity == 0) return;
Node temp = head;
while(temp.next != null) {
if(temp.next.key == key) {
temp.next.value = value;
temp.next.cnt++;
temp.next.timeStamp = curTime;
return;
}
temp = temp.next;
}
if(curSize < capacity) {
curSize++;
temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = new Node(key, value, curTime);
return;
}
else {
int minCnt = Integer.MAX_VALUE;
int minTime = Integer.MAX_VALUE;
Node minNode = null;
temp = head;
while(temp.next != null) {
if(temp.next.cnt < minCnt ||
(temp.next.cnt == minCnt &&
temp.next.timeStamp < minTime)) {
minCnt = temp.next.cnt;
minTime = temp.next.timeStamp;
minNode = temp;
}
temp = temp.next;
}
minNode.next = minNode.next.next;
temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = new Node(key, value, curTime);
}
}
}
class GfG {
public static void main(String[] args) {
LFUCache cache = new LFUCache(2);
cache.put(1, 1);
cache.put(2, 2);
System.out.print(cache.get(1) + " ");
cache.put(3, 3);
System.out.print(cache.get(2) + " ");
cache.put(4, 4);
System.out.print(cache.get(3) + " ");
System.out.print(cache.get(4) + " ");
cache.put(5, 5);
}
}
Python
# Python Program to implement LFU Cache
# singly singly linked list
class Node:
def __init__(self, key, value, timeStamp):
self.key = key
self.value = value
self.cnt = 1
self.timeStamp = timeStamp
self.next = None
# LFU Cache class
class LFUCache:
# Constructor to initialize values
def __init__(self, capacity):
self.capacity = capacity
self.curSize = 0
self.curTime = 0
self.head = Node(-1, -1, -1)
# Function to get the key's value
def get(self, key):
self.curTime += 1
temp = self.head
while temp.next is not None:
if temp.next.key == key:
temp.next.cnt += 1
temp.next.timeStamp = self.curTime
return temp.next.value
temp = temp.next
return -1
# Function to put a key-value pair
def put(self, key, value):
self.curTime += 1
if self.capacity == 0:
return
temp = self.head
while temp.next is not None:
if temp.next.key == key:
temp.next.value = value
temp.next.cnt += 1
temp.next.timeStamp = self.curTime
return
temp = temp.next
if self.curSize < self.capacity:
self.curSize += 1
temp = self.head
while temp.next is not None:
temp = temp.next
temp.next = Node(key, value, self.curTime)
return
else:
minCnt = float('inf')
minTime = float('inf')
minNode = None
temp = self.head
while temp.next is not None:
if temp.next.cnt < minCnt or (
temp.next.cnt == minCnt and temp.next.timeStamp < minTime
):
minCnt = temp.next.cnt
minTime = temp.next.timeStamp
minNode = temp
temp = temp.next
minNode.next = minNode.next.next
temp = self.head
while temp.next is not None:
temp = temp.next
temp.next = Node(key, value, self.curTime)
if __name__ == "__main__":
cache = LFUCache(2)
cache.put(1, 1)
cache.put(2, 2)
print(cache.get(1), end=" ")
cache.put(3, 3)
print(cache.get(2), end=" ")
cache.put(4, 4)
print(cache.get(3), end=" ")
print(cache.get(4), end=" ")
cache.put(5, 5)
C#
// C# Program to implement LFU Cache
// using singly linked list
using System;
class Node {
public int key, value, timeStamp, cnt;
public Node next;
public Node(int key, int value, int timeStamp) {
this.key = key;
this.value = value;
this.cnt = 1;
this.timeStamp = timeStamp;
this.next = null;
}
}
// LFU Cache class
class LFUCache {
private int capacity;
private int curSize;
private int curTime;
Node head;
// Constructor to initialize values
public LFUCache(int capacity) {
this.capacity = capacity;
curSize = 0;
curTime = 0;
head = new Node(-1, -1, -1);
}
// Function to get the key's value
public int Get(int key) {
curTime++;
Node temp = head;
while(temp.next != null) {
if(temp.next.key == key) {
temp.next.cnt++;
temp.next.timeStamp = curTime;
return temp.next.value;
}
temp = temp.next;
}
return -1;
}
// Function to put a key-value pair
public void Put(int key, int value) {
curTime++;
if(capacity == 0) return;
Node temp = head;
while(temp.next != null) {
if(temp.next.key == key) {
temp.next.value = value;
temp.next.cnt++;
temp.next.timeStamp = curTime;
return;
}
temp = temp.next;
}
if(curSize < capacity) {
curSize++;
temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = new Node(key, value, curTime);
return;
}
else {
int minCnt = int.MaxValue;
int minTime = int.MaxValue;
Node minNode = null;
temp = head;
while(temp.next != null) {
if(temp.next.cnt < minCnt ||
(temp.next.cnt == minCnt &&
temp.next.timeStamp < minTime)) {
minCnt = temp.next.cnt;
minTime = temp.next.timeStamp;
minNode = temp;
}
temp = temp.next;
}
minNode.next = minNode.next.next;
temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = new Node(key, value, curTime);
}
}
}
class GfG {
static void Main() {
LFUCache cache = new LFUCache(2);
cache.Put(1, 1);
cache.Put(2, 2);
Console.Write(cache.Get(1) + " ");
cache.Put(3, 3);
Console.Write(cache.Get(2) + " ");
cache.Put(4, 4);
Console.Write(cache.Get(3) + " ");
Console.Write(cache.Get(4) + " ");
cache.Put(5, 5);
}
}
JavaScript
// JavaScript Program to implement LFU Cache
// using singly linked list
class Node {
constructor(key, value, timeStamp) {
this.key = key;
this.value = value;
this.cnt = 1;
this.timeStamp = timeStamp;
this.next = null;
}
}
// LFU Cache class
class LFUCache {
// Constructor to initialize values
constructor(capacity) {
this.capacity = capacity;
this.curSize = 0;
this.curTime = 0;
this.head = new Node(-1, -1, -1);
}
// Function to get the key's value
get(key) {
this.curTime++;
let temp = this.head;
while (temp.next !== null) {
if (temp.next.key === key) {
temp.next.cnt++;
temp.next.timeStamp = this.curTime;
return temp.next.value;
}
temp = temp.next;
}
return -1;
}
// Function to put a key-value pair
put(key, value) {
this.curTime++;
if (this.capacity === 0) return;
let temp = this.head;
while(temp.next != null) {
if(temp.next.key == key) {
temp.next.value = value;
temp.next.cnt++;
temp.next.timeStamp = this.curTime;
return;
}
temp = temp.next;
}
if(this.curSize < this.capacity) {
this.curSize++;
temp = this.head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = new Node(key, value, this.curTime);
return;
}
else {
let minCnt = Infinity, minTime = Infinity;
let minNode = null;
temp = this.head;
while(temp.next != null) {
if(temp.next.cnt < minCnt ||
(temp.next.cnt == minCnt &&
temp.next.timeStamp < minTime)) {
minCnt = temp.next.cnt;
minTime = temp.next.timeStamp;
minNode = temp;
}
temp = temp.next;
}
minNode.next = minNode.next.next;
temp = this.head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = new Node(key, value, this.curTime);
}
}
}
const cache = new LFUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log(cache.get(1) + " ");
cache.put(3, 3);
console.log(cache.get(2) + " ");
cache.put(4, 4);
console.log(cache.get(3) + " ");
console.log(cache.get(4) + " ");
cache.put(5, 5);
Time Complexity: O(n), for each get() and put() operations where n is capacity of cache.
Auxiliary Space: O(capacity)
[Expected Approach] Using Doubly Linked List and Hashing
The idea is to create separate doubly linked list where each DLL stores the nodes with similar frequency from highest to lower priority order. To manage these, create two hash map, first to map the key with its corresponding node and other to map the frequency with head and tail of its corresponding dll. Also, maintain a counter minFreq that keep track of the minimum frequency across all nodes in this cache.
- get (key): Check if key is present in cacheMap or not. If key is not in cacheMap simply return -1, else increment the frequency freq of key by 1 and add the key's node just after the head of dll of frequency freq+1. Also, remove the node from current dll and return the key's value.
- put (key, value): If key is present in cacheMap, update the key-value pair and increment the frequency freq of key by 1. And similar to the get() operation, remove the node from current dll and add it to next dll. Else if key is absent and cache is not full, create the new node corresponding to key-value pair and add this node to dll of frequency 1. Else if cache is full, remove the node connected to the tail of dll of minFreq which is the least frequent node with least priority and add the new node to dll of frequency 1.
illustration:
C++
// C++ Program to implement LFU (Least Frequently Used) cache
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int key;
int value;
int cnt;
Node *next;
Node *prev;
Node(int key, int val) {
this->key = key;
this->value = val;
// Initial frequency is 1
cnt = 1;
}
};
// LFU Cache class
class LFUCache {
public:
// Maps a key to the corresponding Node
unordered_map<int, Node *> cacheMap;
// Maps frequency to a pair of head and tail pointers
unordered_map<int, pair<Node *, Node *>> freqMap;
// Tracks the minimum frequency of the cache
int minFreq;
// Maximum capacity of the cache
int capacity;
// Constructor to initialize LFUCache with a given capacity
LFUCache(int capacity) {
this->capacity = capacity;
// Initial minimum frequency is 0
minFreq = 0;
}
// Function to get the value associated with a key
int get(int key) {
// Return -1 if key is not found in the cache
if (cacheMap.find(key) == cacheMap.end()) {
return -1;
}
// Retrieve the Node and update its frequency
Node *node = cacheMap[key];
int res = node->value;
updateFreq(node);
return res;
}
// Function to add or update a key-value pair in the cache
void put(int key, int value) {
// Do nothing if the cache has zero capacity
if (capacity == 0)
return;
// Update value if key already exists in the cache
if (cacheMap.find(key) != cacheMap.end()) {
Node *node = cacheMap[key];
node->value = value;
updateFreq(node);
}
// Add a new key-value pair to the cache
else {
// Remove the least frequently used node if cache is full
if (cacheMap.size() == capacity) {
Node *node = freqMap[minFreq].second->prev;
cacheMap.erase(node->key);
remove(node);
// Remove the frequency list if it's empty
if (freqMap[minFreq].first->next == freqMap[minFreq].second) {
freqMap.erase(minFreq);
}
// Free memory
delete node;
}
// Create a new node for the key-value pair
Node *node = new Node(key, value);
cacheMap[key] = node;
// Reset minimum frequency to 1
minFreq = 1;
add(node, 1);
}
}
// Add a node to the frequency list
void add(Node *node, int freq) {
// Initialize the frequency list if it doesn't exist
if (freqMap.find(freq) == freqMap.end()) {
// Dummy head node
Node *head = new Node(-1, -1);
// Dummy tail node
Node *tail = new Node(-1, -1);
head->next = tail;
tail->prev = head;
freqMap[freq] = {head, tail};
}
// Insert the node right after the head
Node *head = freqMap[freq].first;
Node *temp = head->next;
node->next = temp;
node->prev = head;
head->next = node;
temp->prev = node;
}
// Remove a node from the frequency list
void remove(Node *node) {
// Update pointers to exclude the node
Node *delprev = node->prev;
Node *delnext = node->next;
delprev->next = delnext;
delnext->prev = delprev;
}
// Update the frequency of a node
void updateFreq(Node *node) {
// Get the current frequency
int oldFreq = node->cnt;
// Increment the frequency
node->cnt++;
// Remove the node from the current frequency list
remove(node);
// Remove the frequency list if it becomes empty
if (freqMap[oldFreq].first->next == freqMap[oldFreq].second) {
freqMap.erase(oldFreq);
// Update minimum frequency if needed
if (minFreq == oldFreq) {
minFreq++;
}
}
// Add the node to the updated frequency list
add(node, node->cnt);
}
};
int main() {
LFUCache cache(2);
cache.put(1, 1);
cache.put(2, 2);
cout << cache.get(1) << " ";
cache.put(3, 3);
cout << cache.get(2) << " ";
cache.put(4, 4);
cout << cache.get(3) << " ";
cout << cache.get(4) << " ";
cache.put(5, 5);
return 0;
}
Java
// Java program to implement LFU (Least Frequently Used)
// using hashing
import java.util.*;
class Node {
int key;
int value;
int cnt;
Node next;
Node prev;
Node(int key, int val) {
this.key = key;
this.value = val;
// Initial frequency is 1
cnt = 1;
}
}
class LFUCache {
// Maps key to the Node
private Map<Integer, Node> cacheMap;
// Maps frequency to doubly linked list
//(head, tail) of Nodes with that frequency
private Map<Integer, Pair<Node, Node> > freqMap;
// Tracks the minimum frequency
private int minFreq;
// Capacity of the LFU cache
private int capacity;
// Constructor to initialize LFUCache with a given capacity
LFUCache(int capacity) {
this.capacity = capacity;
// Initial minimum frequency is 0
minFreq = 0;
cacheMap = new HashMap<>();
freqMap = new HashMap<>();
}
// Function to get the value for a given key
int get(int key) {
// Return -1 if key is not found in the cache
if (!cacheMap.containsKey(key)) {
return -1;
}
// Retrieve the Node and update its frequency
Node node = cacheMap.get(key);
int res = node.value;
updateFreq(node);
return res;
}
// Function to put a key-value pair into the cache
void put(int key, int value) {
// Do nothing if the cache has zero capacity
if (capacity == 0) {
return;
}
// Update value if key already exists in the cache
if (cacheMap.containsKey(key)) {
Node node = cacheMap.get(key);
node.value = value;
updateFreq(node);
}
// Add a new key-value pair to the cache
else {
// Remove the least frequently used node if cache is full
if (cacheMap.size() == capacity) {
Node node
= freqMap.get(minFreq).second.prev;
cacheMap.remove(node.key);
remove(node);
// Remove the frequency list if it's empty
if (freqMap.get(minFreq).first.next
== freqMap.get(minFreq).second) {
freqMap.remove(minFreq);
}
}
// Create a new node for the key-value pair
Node node = new Node(key, value);
cacheMap.put(key, node);
// Reset minimum frequency to 1
minFreq = 1;
add(node, 1);
}
}
// Add a node right after the head
void add(Node node, int freq) {
// Initialize the frequency list if it doesn't exist
if (!freqMap.containsKey(freq)) {
// Dummy head node
Node head = new Node(-1, -1);
// Dummy tail node
Node tail = new Node(-1, -1);
head.next = tail;
tail.prev = head;
freqMap.put(freq, new Pair<>(head, tail));
}
// Insert the node right after the head
Node head = freqMap.get(freq).first;
Node temp = head.next;
node.next = temp;
node.prev = head;
head.next = node;
temp.prev = node;
}
// Remove a node from the list
void remove(Node node) {
// Update pointers to exclude the node
Node delprev = node.prev;
Node delnext = node.next;
delprev.next = delnext;
delnext.prev = delprev;
}
// Update the frequency of a node
void updateFreq(Node node) {
// Get the current frequency
int oldFreq = node.cnt;
// Increment the frequency
node.cnt++;
// Remove the node from the current frequency list
remove(node);
if (freqMap.get(oldFreq).first.next
== freqMap.get(oldFreq).second) {
freqMap.remove(oldFreq);
// Update minimum frequency if needed
if (minFreq == oldFreq) {
minFreq++;
}
}
// Add the node to the updated frequency list
add(node, node.cnt);
}
static class Pair<F, S> {
F first;
S second;
Pair(F first, S second) {
this.first = first;
this.second = second;
}
}
}
class GfG {
public static void main(String[] args) {
LFUCache cache = new LFUCache(2);
cache.put(1, 1);
cache.put(2, 2);
System.out.print(cache.get(1) + " ");
cache.put(3, 3);
System.out.print(cache.get(2) + " ");
cache.put(4, 4);
System.out.print(cache.get(3) + " ");
System.out.print(cache.get(4) + " ");
cache.put(5, 5);
}
}
Python
# Python program to implement LFU (Least Frequently Used)
# using hashing
class Node:
def __init__(self, key, val):
self.key = key
self.value = val
# Initial frequency is 1
self.cnt = 1
self.next = None
self.prev = None
class LFUCache:
# Constructor to initialize the LFU cache
def __init__(self, capacity):
# Maps key to Node
self.cacheMap = {}
# Maps frequency to doubly linked list
# (head, tail) of Nodes
self.freqMap = {}
# Tracks the minimum frequency
self.minFreq = 0
# Capacity of the LFU cache
self.capacity = capacity
# Function to get the value for a given key
def get(self, key):
# Return -1 if key is not found in the cache
if key not in self.cacheMap:
return -1
# Retrieve the Node and update its frequency
node = self.cacheMap[key]
res = node.value
self.updateFreq(node)
return res
# Function to put a key-value pair into the cache
def put(self, key, value):
# Do nothing if the cache has zero capacity
if self.capacity == 0:
return
# Update value if key already exists in the cache
if key in self.cacheMap:
node = self.cacheMap[key]
node.value = value
self.updateFreq(node)
# Add a new key-value pair to the cache
else:
# Remove the least frequently used node if cache is full
if len(self.cacheMap) == self.capacity:
node = self.freqMap[self.minFreq][1].prev
del self.cacheMap[node.key]
self.remove(node)
# Remove the frequency list if it's empty
if self.freqMap[self.minFreq][0].next == self.freqMap[self.minFreq][1]:
del self.freqMap[self.minFreq]
# Create a new node for the key-value pair
node = Node(key, value)
self.cacheMap[key] = node
# Reset minimum frequency to 1
self.minFreq = 1
self.add(node, 1)
# Add a node right after the head
def add(self, node, freq):
# Initialize the frequency list if it doesn't exist
if freq not in self.freqMap:
# Dummy head node
head = Node(-1, -1)
# Dummy tail node
tail = Node(-1, -1)
head.next = tail
tail.prev = head
self.freqMap[freq] = (head, tail)
# Insert the node right after the head
head = self.freqMap[freq][0]
temp = head.next
node.next = temp
node.prev = head
head.next = node
temp.prev = node
# Remove a node from the list
def remove(self, node):
# Update pointers to exclude the node
delprev = node.prev
delnext = node.next
delprev.next = delnext
delnext.prev = delprev
# Update the frequency of a node
def updateFreq(self, node):
# Get the current frequency
oldFreq = node.cnt
# Increment the frequency
node.cnt += 1
# Remove the node from the current frequency list
self.remove(node)
if self.freqMap[oldFreq][0].next == self.freqMap[oldFreq][1]:
del self.freqMap[oldFreq]
# Update minimum frequency if needed
if self.minFreq == oldFreq:
self.minFreq += 1
# Add the node to the updated frequency list
self.add(node, node.cnt)
if __name__ == "__main__":
cache = LFUCache(2)
cache.put(1, 1)
cache.put(2, 2)
print(cache.get(1), end=" ")
cache.put(3, 3)
print(cache.get(2), end=" ")
cache.put(4, 4)
print(cache.get(3), end=" ")
print(cache.get(4), end=" ")
cache.put(5, 5)
C#
// C# program to implement LFU (Least Frequently Used)
// using hashing
using System;
using System.Collections.Generic;
class Node {
public int key;
public int value;
public int cnt;
public Node next;
public Node prev;
public Node(int key, int val) {
this.key = key;
this.value = val;
// Initial frequency is 1
cnt = 1;
}
}
class LFUCache {
// Maps key to the Node
private Dictionary<int, Node> cacheMap;
// Maps frequency to doubly linked list
// (head, tail) of Nodes with that frequency
private Dictionary<int, Pair<Node, Node>> freqMap;
// Tracks the minimum frequency
private int minFreq;
// Capacity of the LFU cache
private int capacity;
// Constructor to initialize LFUCache with a given
// capacity
public LFUCache(int capacity) {
this.capacity = capacity;
// Initial minimum frequency is 0
minFreq = 0;
cacheMap = new Dictionary<int, Node>();
freqMap = new Dictionary<int, Pair<Node, Node> >();
}
// Function to get the value for a given key
public int Get(int key) {
// Return -1 if key is not found in the cache
if (!cacheMap.ContainsKey(key)) {
return -1;
}
// Retrieve the Node and update its frequency
Node node = cacheMap[key];
int res = node.value;
UpdateFreq(node);
return res;
}
// Function to put a key-value pair into the cache
public void Put(int key, int value) {
// Do nothing if the cache has zero capacity
if (capacity == 0) {
return;
}
// Update value if key already exists in the cache
if (cacheMap.ContainsKey(key)) {
Node node = cacheMap[key];
node.value = value;
UpdateFreq(node);
}
// Add a new key-value pair to the cache
else {
// Remove the least frequently used node if
// cache is full
if (cacheMap.Count == capacity) {
Node node = freqMap[minFreq].second.prev;
cacheMap.Remove(node.key);
Remove(node);
// Remove the frequency list if it's empty
if (freqMap[minFreq].first.next
== freqMap[minFreq].second) {
freqMap.Remove(minFreq);
}
}
// Create a new node for the key-value pair
Node newNode = new Node(key, value);
cacheMap[key] = newNode;
// Reset minimum frequency to 1
minFreq = 1;
Add(newNode, 1);
}
}
// Add a node right after the head
private void Add(Node node, int freq) {
// Initialize the frequency list if it doesn't exist
if (!freqMap.ContainsKey(freq)) {
// Dummy head node
Node head = new Node(-1, -1);
// Dummy tail node
Node tail = new Node(-1, -1);
head.next = tail;
tail.prev = head;
freqMap[freq]
= new Pair<Node, Node>(head, tail);
}
// Insert the node right after the head
Node headNode = freqMap[freq].first;
Node temp = headNode.next;
node.next = temp;
node.prev = headNode;
headNode.next = node;
temp.prev = node;
}
// Remove a node from the list
private void Remove(Node node) {
// Update pointers to exclude the node
Node delprev = node.prev;
Node delnext = node.next;
delprev.next = delnext;
delnext.prev = delprev;
}
// Update the frequency of a node
private void UpdateFreq(Node node) {
// Get the current frequency
int oldFreq = node.cnt;
// Increment the frequency
node.cnt++;
// Remove the node from the current frequency list
Remove(node);
if (freqMap[oldFreq].first.next
== freqMap[oldFreq].second) {
freqMap.Remove(oldFreq);
// Update minimum frequency if needed
if (minFreq == oldFreq) {
minFreq++;
}
}
// Add the node to the updated frequency list
Add(node, node.cnt);
}
// Helper class to represent a pair of nodes
private class Pair<F, S> {
public F first;
public S second;
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
}
}
class GfG {
static void Main(string[] args) {
LFUCache cache = new LFUCache(2);
cache.Put(1, 1);
cache.Put(2, 2);
Console.Write(cache.Get(1) + " ");
cache.Put(3, 3);
Console.Write(cache.Get(2) + " ");
cache.Put(4, 4);
Console.Write(cache.Get(3) + " ");
Console.Write(cache.Get(4) + " ");
cache.Put(5, 5);
}
}
JavaScript
// JavaScript program to implement LFU (Least Frequently
// Used) using hashing
class Node {
constructor(key, val) {
this.key = key;
this.value = val;
// Initial frequency is 1
this.cnt = 1;
this.next = null;
this.prev = null;
}
}
class LFUCache {
// Constructor to initialize LFUCache with a given
// capacity
constructor(capacity) {
// Maps key to the Node
this.cacheMap = new Map();
// Maps frequency to doubly linked list
// (head, tail) of Nodes with that frequency
this.freqMap = new Map();
// Tracks the minimum frequency
this.minFreq = 0;
// Capacity of the LFU cache
this.capacity = capacity;
}
get(key) {
// Return -1 if key is not found in the cache
if (!this.cacheMap.has(key)) {
return -1;
}
// Retrieve the Node and update its frequency
const node = this.cacheMap.get(key);
const res = node.value;
this.updateFreq(node);
return res;
}
// Function to put a key-value pair into the cache
put(key, value) {
// Do nothing if the cache has zero capacity
if (this.capacity === 0)
return;
// Update value if key already exists in the cache
if (this.cacheMap.has(key)) {
const node = this.cacheMap.get(key);
node.value = value;
this.updateFreq(node);
}
// Add a new key-value pair to the cache
else {
// Remove the least frequently used node if
// cache is full
if (this.cacheMap.size === this.capacity) {
const node = this.freqMap.get(this.minFreq)
.tail.prev;
this.cacheMap.delete(node.key);
this.remove(node);
// Remove the frequency list if it's empty
if (this.freqMap.get(this.minFreq).head.next
=== this.freqMap.get(this.minFreq)
.tail) {
this.freqMap.delete(this.minFreq);
}
}
// Create a new node for the key-value pair
const node = new Node(key, value);
this.cacheMap.set(key, node);
// Reset minimum frequency to 1
this.minFreq = 1;
this.add(node, 1);
}
}
// Add a node right after the head
add(node, freq) {
// Initialize the frequency list if it doesn't exist
if (!this.freqMap.has(freq)) {
// Dummy head node
const head = new Node(-1, -1);
// Dummy tail node
const tail = new Node(-1, -1);
head.next = tail;
tail.prev = head;
this.freqMap.set(freq, {head, tail});
}
// Insert the node right after the head
const head = this.freqMap.get(freq).head;
const temp = head.next;
node.next = temp;
node.prev = head;
head.next = node;
temp.prev = node;
}
// Remove a node from the list
remove(node) {
// Update pointers to exclude the node
const delprev = node.prev;
const delnext = node.next;
delprev.next = delnext;
delnext.prev = delprev;
}
// Update the frequency of a node
updateFreq(node) {
// Get the current frequency
const oldFreq = node.cnt;
// Increment the frequency
node.cnt++;
// Remove the node from the current frequency list
this.remove(node);
if (this.freqMap.get(oldFreq).head.next
=== this.freqMap.get(oldFreq).tail) {
this.freqMap.delete(oldFreq);
// Update minimum frequency if needed
if (this.minFreq === oldFreq) {
this.minFreq++;
}
}
// Add the node to the updated frequency list
this.add(node, node.cnt);
}
}
const cache = new LFUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log(cache.get(1) + " ");
cache.put(3, 3);
console.log(cache.get(2) + " ");
cache.put(4, 4);
console.log(cache.get(3) + " ");
console.log(cache.get(4) + " ");
cache.put(5, 5);
Time Complexity : get(key) - O(1) and put(key, value) - O(1)
Auxiliary Space : O(capacity)
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem