diff --git a/README.md b/README.md index 0af407ea..72098182 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,9 @@ Collection of interview questions with Unit Tests. Problems includes Data Struct - [Queue](src/_DataStructures_/Queue) - [Weave](src/_DataStructures_/Queue/weave) +- [Doubly Linked List](src/_DataStructures_/DoublyLinkedList) - [Suffix Tree](src/_DataStructures_/SuffixTree) - ### Logical Problems - [Anagrams](src/_Problems_/anagrams) @@ -63,6 +63,11 @@ Collection of interview questions with Unit Tests. Problems includes Data Struct - [Binary Search](src/_Searching_/BinarySearch) +### Algorithms + +- [LRU Cache](src/_Algorithms_/lru-cache) + + ### Path Finder - [A\*](src/PathFinder/AStart) diff --git a/src/_Algorithms_/lru-cache/index.js b/src/_Algorithms_/lru-cache/index.js new file mode 100644 index 00000000..beb96347 --- /dev/null +++ b/src/_Algorithms_/lru-cache/index.js @@ -0,0 +1,71 @@ +/* +Least recently used (LRU) - cache implementation + +get(key) – Get the value (will always be positive) of the key if the key exists in the cache, otherwise return false. +Complexity: O(1) + +set(key, value) – Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. +Complexity: O(1) +*/ + +const DoublyLinkedList = require('../../_DataStructures_/DoublyLinkedList/index'); + +class LRUCache { + constructor(n) { + this.size = n; + this.map = new Map(); + this.list = new DoublyLinkedList(); + } + + // this method will work in O(1) + set(key, value) { + const data = { + key, + value, + }; + if (!this.map.has(key)) { + this.list.addAtBeginning(data); + this.map.set(key, this.list.head.next); + + if (this.list.length() > this.size) { + const lastNode = this.list.tail.previous.data; + this.map.delete(lastNode.key); + this.list.removeAtEnd(); + } + } else { + this.list.remove(this.map.get(key)); + this.list.addAtBeginning(data); + this.map.set(key, this.list.head.next); + } + } + + // this method will work in O(1) + get(key) { + if (this.map.has(key)) { + const node = this.map.get(key); + const { value } = node.data; + this.list.remove(node); + this.list.addAtBeginning({ + key, + value, + }); + this.map.set(key, this.list.head.next); + } + return false; + } +} + +// const lru = new LRUCache(3); +// lru.set(1, 1); +// lru.set(2, 2); +// lru.set(3, 3); +// lru.set(4, 4); +// lru.set(5, 5); +// lru.set(2, 2); +// lru.get(5, 5); +// lru.list.display(); + + +module.exports = { + LRUCache, +}; diff --git a/src/_DataStructures_/DoublyLinkedList/index.js b/src/_DataStructures_/DoublyLinkedList/index.js new file mode 100644 index 00000000..522924b9 --- /dev/null +++ b/src/_DataStructures_/DoublyLinkedList/index.js @@ -0,0 +1,65 @@ +/* eslint-disable class-methods-use-this */ +class Node { + constructor(data, previous, next) { + this.data = data; + this.previous = previous; + this.next = next; + } +} + +class DoublyLinkedList { + constructor() { + // head -> tail + // head <- tail + this.head = new Node(null, null, null); + this.tail = new Node(null, null, null); + this.head.next = this.tail; // head next point to tail + this.tail.previous = this.head; // tail previous point to head + this.size = 0; + } + + addAtBeginning(value) { + const newNode = new Node(value, this.head, this.head.next); + this.head.next.previous = newNode; + this.head.next = newNode; + this.size += 1; + } + + addAtEnd(value) { + const newNode = new Node(value, this.tail.previous, this.tail); + this.tail.previous.next = newNode; + this.tail.previous = newNode; + this.size += 1; + } + + removeAtBeginning() { + this.remove(this.head.next); + this.size -= 1; + } + + removeAtEnd() { + this.remove(this.tail.previous); + this.size -= 1; + } + + remove(node) { + const previousNode = node.previous; + const nextNode = node.next; + previousNode.next = nextNode; + nextNode.previous = previousNode; + } + + length() { + return this.size; + } + + display() { + let address = this.head.next; + while (address !== this.tail) { + console.log(address.data); + address = address.next; + } + } +} + +module.exports = DoublyLinkedList;