JavaScript Map and Big O Notation

[IMAGE_PLACEHOLDER]
Understanding the time complexity (Big O notation) of Map
operations is essential for building efficient algorithms. In this post, we’ll explore the Big O notation of Map
operations and how they can be utilized to improve algorithm performance.
Big O Notation of Map Operations
-
Insertion (
set
): O(1)- Adding a key-value pair to a
Map
is generally an O(1) operation because it involves hashing the key and placing the value in the appropriate bucket.
- Adding a key-value pair to a
-
Deletion (
delete
): O(1)- Deleting a key-value pair from a
Map
is O(1) on average, as it typically involves hashing the key and removing the associated value from the bucket.
- Deleting a key-value pair from a
-
Check Existence (
has
): O(1)- Checking if a key exists in a
Map
is an O(1) operation, requiring the key to be hashed and then checking the corresponding bucket.
- Checking if a key exists in a
-
Retrieval (
get
): O(1)- Retrieving the value associated with a key in a
Map
is O(1) because the key is hashed and the corresponding value is looked up directly.
- Retrieving the value associated with a key in a
-
Iteration: O(n)
- Iterating over all key-value pairs in a
Map
is O(n), where n is the number of elements in theMap
.
- Iterating over all key-value pairs in a
Practical Examples of Using Map
for Efficient Algorithms
Example 1: Counting Occurrences in an Array
Problem: Count the number of occurrences of each element in an array.
Solution: Use a Map
to store the element as the key and its count as the value.
function countOccurrences(arr) {
const map = new Map()
for (let item of arr) {
map.set(item, (map.get(item) || 0) + 1)
}
return map
}
const numbers = [1, 2, 2, 3, 3, 3, 4]
console.log(countOccurrences(numbers))
// Output: Map { 1 => 1, 2 => 2, 3 => 3, 4 => 1 }
Analysis:
- Time Complexity: O(n) for iterating over the array and updating the count in the
Map
. - Space Complexity: O(n) for storing the counts of unique elements.
Example 2: Checking for Duplicate Keys
Problem: Check if a list of objects has duplicate keys.
Solution: Use a Map
to track keys and detect duplicates efficiently.
function hasDuplicateKeys(objects) {
const map = new Map()
for (let obj of objects) {
for (let key of Object.keys(obj)) {
if (map.has(key)) {
return true
}
map.set(key, true)
}
}
return false
}
const objects = [{ a: 1 }, { b: 2 }, { a: 3 }]
console.log(hasDuplicateKeys(objects)) // Output: true
Analysis:
- Time Complexity: O(n), where n is the total number of keys.
- Space Complexity: O(n) for storing the keys in the
Map
.
Example 3: Grouping Elements by Key
Problem: Group an array of objects by a common key.
Solution: Use a Map
to group objects by a specific key.
function groupBy(arr, key) {
const map = new Map()
for (let obj of arr) {
const keyValue = obj[key]
if (!map.has(keyValue)) {
map.set(keyValue, [])
}
map.get(keyValue).push(obj)
}
return map
}
const people = [
{ name: 'John', age: 25 },
{ name: 'Jane', age: 30 },
{ name: 'Jim', age: 25 },
]
console.log(groupBy(people, 'age'))
// Output: Map { 25 => [{ name: 'John', age: 25 }, { name: 'Jim', age: 25 }], 30 => [{ name: 'Jane', age: 30 }] }
Analysis:
- Time Complexity: O(n) for iterating over the array and grouping objects by the specified key.
- Space Complexity: O(n) for storing the groups in the
Map
.
Example 4: Efficient LRU Cache Implementation
Problem: Implement a Least Recently Used (LRU) cache using a Map
.
Solution: Use a Map
where the keys represent cache entries and the values represent the data.
class LRUCache {
constructor(capacity) {
this.capacity = capacity
this.cache = new Map()
}
get(key) {
if (!this.cache.has(key)) {
return -1
}
const value = this.cache.get(key)
this.cache.delete(key)
this.cache.set(key, value)
return value
}
put(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key)
}
this.cache.set(key, value)
if (this.cache.size > this.capacity) {
this.cache.delete(this.cache.keys().next().value)
}
}
}
const lru = new LRUCache(2)
lru.put(1, 1)
lru.put(2, 2)
console.log(lru.get(1)) // Output: 1
lru.put(3, 3)
console.log(lru.get(2)) // Output: -1 (2 is evicted)
Analysis:
- Time Complexity: O(1) for both
get
andput
operations. - Space Complexity: O(n) for storing the cache entries in the
Map
.
Summary
- Insertion, Deletion, Existence Check, and Retrieval: All have O(1) average time complexity, making
Map
highly efficient for operations requiring key-value pairs and fast lookups. - Iteration: O(n) time complexity for iterating over all elements.
By leveraging Map
for fast key-value storage and retrieval, you can optimize algorithms that involve frequent lookups, caching, or grouping of data.