题解 | #设计LRU缓存结构#
设计LRU缓存结构
http://www.nowcoder.com/practice/e3769a5f49894d49b871c09cadd13a61
LRU-自建双向链表
使用LinkedHashMap的同学可以歇歇了,面试你用LinkedHashMap试试:)
所以这里提供自建方案,学习自lc
import java.util.*; public class Solution { // 链表节点,用于存放数据,为HashMap提供顺序 private class Node { int key; int value; Node pre; Node next; public Node(){} public Node(int key, int value) { this.key = key; this.value = value; } } Node head; // 头节点 Node tail; // 尾节点 int size; // 容量 int capacity; // 容量上限 Map<Integer, Node> cache; // 方便查找节点,实现O(1)查找时间复杂度 /** * lru design * @param operators int整型二维数组 the ops * @param k int整型 the k * @return int整型一维数组 */ public int[] LRU (int[][] operators, int k) { // write code here init(k); List<Integer> res = new ArrayList<>(); for (int[] o : operators) { if (o[0] == 1) { set(o[1], o[2]); } else { res.add(get(o[1])); } } return res.stream().mapToInt(Integer::intValue).toArray(); } // 初始化LRU private void init(int capacity) { this.size = 0; this.capacity = capacity; cache = new HashMap<>(); head = new Node(); tail = new Node(); head.next = tail; tail.pre = head; } // 查找节点 private int get(int key) { Node node = cache.get(key); if (node == null) return -1; // 不存在返回-1; moveToHead(node); //存在则将节点移至链表头部 return node.value; } // 设置节点 private void set(int key, int value) { Node node = cache.get(key); if (node == null) { // 节点不存在,新建节点并插入链表头部和哈希表 node = new Node(key, value); addToHead(node); cache.put(key, node); size++; if (size > capacity) { // 容量超过容量上限,则移除链表尾部,并删除对应哈希表数据 cache.remove(tail.pre.key); removeNode(tail.pre); size--; } } else { // 节点已存在,则修改value,并将节点移至头部 node.value = value; moveToHead(node); } } // 将链表节点移至链表头部 private void moveToHead(Node node) { removeNode(node); addToHead(node); } // 将节点移除 private void removeNode(Node node) { node.pre.next = node.next; node.next.pre = node.pre; } // 将节点添加至链表头部 private void addToHead(Node node) { node.next = head.next; node.pre = head; node.next.pre = node; node.pre.next = node; } }