LRU cache design

后端 未结 11 1990
借酒劲吻你
借酒劲吻你 2020-11-27 09:26

Least Recently Used (LRU) Cache is to discard the least recently used items first How do you design and implement such a cache class? The design requirements are as follows:

11条回答
  •  难免孤独
    2020-11-27 10:10

    Detailed explanation here in my blogpost.

    class LRUCache {
      constructor(capacity) {
        
            this.head = null;
            this.tail = null;
            this.capacity = capacity;
            this.count = 0;
        this.hashMap  = new Map();    
      }
     
      get(key) {
        var node = this.hashMap.get(key);
        if(node) {
          if(node == this.head) {
            // node is already at the head, just return the value
            return node.val;
          }      
          if(this.tail == node && this.tail.prev) {
            // if the node is at the tail,
            // set tail to the previous node if it exists.
            this.tail = this.tail.prev;
            this.tail.next = null;
          }
          // link neibouring nodes together
          if(node.prev)
            node.prev.next = node.next;
          if(node.next)
            node.next.prev = node.prev;      
          // add the new head node
          node.prev = null;
          node.next = this.head;
          this.head.prev = node;
          this.head = node;
          return node.val;
        }
        return -1;
      }
      put(key, val) {
        this.count ++;
        var newNode = { key, val, prev: null, next: null };
        if(this.head == null) {
          // this.hashMap is empty creating new node
          this.head =  newNode;
          this.tail = newNode;
        }
        else {
          var oldNode = this.hashMap.get(key);
          if(oldNode) {
            // if node with the same key exists, 
            // clear prev and next pointers before deleting the node.
            if(oldNode.next) {
              if(oldNode.prev)
                oldNode.next.prev = oldNode.prev;
              else
                this.head = oldNode.next;
            }
            if(oldNode.prev) {          
              oldNode.prev.next = oldNode.next;
              if(oldNode == this.tail)
                this.tail = oldNode.prev;
            }
            // removing the node
            this.hashMap.delete(key);
            this.count --;        
          }
          // adding the new node and set up the pointers to it's neibouring nodes      
          var currentHead = this.head;
          currentHead.prev = newNode;        
          newNode.next = currentHead;
          this.head = newNode;
          if(this.tail == null)
            this.tail = currentHead;
          if(this.count == this.capacity + 1) {
            // remove last nove if over capacity
            var lastNode = this.tail;
            this.tail = lastNode.prev;
            if(!this.tail) {
              //debugger;
            }
            this.tail.next = null;
            this.hashMap.delete(lastNode.key);
            this.count --;
          }
        }
        this.hashMap.set(key, newNode);
        return null;
      }
    }
    
    var cache = new LRUCache(3);
    cache.put(1,1); // 1
    cache.put(2,2); // 2,1
    cache.put(3,3); // 3,2,1
    
    console.log( cache.get(2) ); // 2,3,1
    console.log( cache.get(1) ); // 1,2,3
    cache.put(4,4);              // 4,1,2 evicts 3
    console.log( cache.get(3) ); // 3 is no longer in cache

提交回复
热议问题