LeetCode Solutions

LRU 缓存

Jump to Section

LRU 缓存机制 146

// ../../../../../src/main/java/com/dll/leetcode/LRUCache146.java

package com.dll.leetcode;

import java.util.HashMap;
import java.util.Map;

public class LRUCache146 {

  class DoubleLinkedList {
    private Map<Integer, Node> map;
    private Node head;
    private Node tail;
    private int size;

    public int getSize() {
      return this.size;
    }

    private DoubleLinkedList() {
      head = new Node(null, -1, -1, null);
      tail = new Node(null, -1, -1, null);
      head.next = tail;
      tail.prev = head;
      this.map = new HashMap<>();
    }

    class Node {
      int key;
      int value;
      Node prev;
      Node next;

      Node(Node prev, int key, int value, Node next) {
        this.key = key;
        this.prev = prev;
        this.value = value;
        this.next = next;
      }
    }

    private boolean containsKey(int key) {
      return this.map.containsKey(key);
    }

    public Node get(int key) {
      return this.map.getOrDefault(key, null);
    }

    public void delete(Node node) {
      Node prev = node.prev;
      Node next = node.next;
      prev.next = next;
      next.prev = prev;
      this.map.remove(node.key);
      this.size--;
    }

    private Node addFirst(int key, int value) {
      Node node = new Node(head, key, value, head.next);
      head.next.prev = node;
      head.next = node;
      this.size++;
      this.map.put(key, node);
      return node;
    }

    private Node deleteLast() {
      Node deletedPrev = tail.prev.prev;
      Node deleted = deletedPrev.next;
      deletedPrev.next = tail;
      tail.prev = deletedPrev;
      this.map.remove(deleted.key);
      return deleted;
    }

  }

  private DoubleLinkedList list = new DoubleLinkedList();
  private int capacity;

  public LRUCache146(int capacity) {
    if (capacity <= 0) {
      throw new RuntimeException();
    }
    this.capacity = capacity;
  }

  /**
   * get value by key from cache
   * @param key key of cache
   * @return value of key
   */
  public int get(int key) {
    DoubleLinkedList.Node node = list.get(key);
    if (node == null) {
      return -1;
    }
    list.delete(node);
    list.addFirst(node.key, node.value);
    return node.value;
  }

  /**
   * put key and value to cache
   * @param key key of cache
   * @param value value of key
   */
  public void put(int key, int value) {
    // 1. exist in map -> remove(value) & push(value)
    // 2. don't exist in map -> deque is full -> removeLast & push(value)
    // 3. don't exist in map -> deque is empty -> push(value)
    if (list.containsKey(key)) {
      list.delete(list.get(key));
    } else {
      if (list.getSize() >= this.capacity) {
        list.deleteLast();
      }
    }
    list.addFirst(key, value);
  }
}