LeetCode Brush Questions - LRU Cache

LRU cache

topic

Implement the LRUCache class:

  • LRUCache(int capacity) Initialize the LRU cache with a positive integer as the capacity capacity
  • int get(int key) Returns the value of the key if the key key exists in the cache, otherwise returns -1.
  • void put(int key, int value) If the key already exists, change its data value; if the key does not exist, insert the set of "key-value". When the cache capacity reaches its upper limit, it should delete the oldest unused data values ​​before writing new data, thus making room for new data values.

Source: Link to LeetCode

train of thought

Maintain a doubly linked list and a hash table. The hash table stores keys and corresponding linked list nodes. The head of the doubly linked list is the longest unused value, and the tail is the most recently used value. Therefore, to remove the longest unused value, just remove The head node of the linked list; updating the most recently used value only needs to move the corresponding node to the end of the linked list

class LRUCache {
    
    
	class Node {
    
    
		int key;
		int value;
		Node last;
		Node next;
		Node() {
    
    };
		Node(int key, int value) {
    
    
			this.key = key;
			this.value = value;
		}
	}

	int capacity; // 容量
	HashMap<Integer, Node> map; 
	Node head; // 双向链表头
	Node tail; // 双向链表尾

	LRUCache(int cap) {
    
    
		capacity = cap;
		map = new HashMap<>();
		head = null;
		tail = null;
	}

	public int get(int key) {
    
    
		if (!map.containsKey(key)) {
    
    
			return -1;
		} else {
    
    
			Node node = map.get(key);
			moveNodeToTail(node);
			return node.value;
		}
	}

	public void put(int key, int value) {
    
    
		if (map.containsKey(key)) {
    
    
			Node node = map.get(key);
			node.value = value;
      		moveNodeToTail(node);
		} else {
    
    
			Node newNode = new Node(key, value);
			map.put(key, newNode);
			addNode(newNode);
			if (map.size() > capacity) {
    
     // 检查是否超出容量,若超出则移除链表头结点
				Node head = removeHead();
				map.remove(head.key);
			}
		}
	}

	public void addNode(Node node) {
    
    
		if (node == null) {
    
    
			return;
		}
		// 若链表中无结点,则将头尾都指向新结点;否则将新结点挂在尾部
		if (head == null) {
    
    
			head = node;
			tail = node;
		} else {
    
    
			tail.next = node;
			node.last = tail;
			tail = node;
		}
	}

	public void moveNodeToTail(Node node) {
    
    
		if (node == null || head == tail || node == tail) {
    
     // 若链表只有一个结点,或者当前结点就是尾结点,直接return即可
			return;
		}
		if (node == head) {
    
    
			head = node.next;
			head.last = null;
		} else {
    
    
			node.last.next = node.next;
			node.next.last = node.last;
		}
		tail.next = node;
		node.last = tail;
		node.next = null;
		tail = node;

	}

	public Node removeHead() {
    
    
		if (head == null) {
    
    
			return null;
		}
		Node res = head;
		if (head == tail) {
    
    
			head = null;
			tail = null;
		} else {
    
    
			head = res.next;
			res.next = null;
			head.last = null;
		}
		return res;
	}
}

Guess you like

Origin blog.csdn.net/wzc3614/article/details/129476064