请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
面试比较高频,并且涵盖了很多知识点。这里手动实现了双向链表DoubleLink类。
需要注意各个情况下链表的处理,其实逻辑不难。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 class LRUCache { class Node { public Node pre; public Node next; public int key; public int value; public Node (int key, int value) { this .key = key; this .value = value; } } class DoubleLink { public Node head; public Node tail; private int size; public void addFirst (Node node) { if (head == null ) { head = node; tail = node; } else { Node oldHead = head; oldHead.pre = node; node.next = oldHead; head = node; } size++; } public void remove (Node node) { if (head == node && tail == node) { head = null ; tail = null ; } else if (node == head) { node.next.pre = null ; head = node.next; } else if (node == tail) { node.pre.next = null ; tail = node.pre; } else { node.pre.next = node.next; node.next.pre = node.pre; } size--; } public Node removeLast () { Node node = tail; remove(tail); return node; } public int size () { return this .size; } } private Map<Integer, Node> map; private DoubleLink cache; private int cap; public LRUCache (int capacity) { this .cap = capacity; map = new HashMap <>(); cache = new DoubleLink (); } public int get (int key) { if (!map.containsKey(key)) { return -1 ; } int val = map.get(key).value; put(key, val); return val; } public void put (int key, int value) { Node node = new Node (key, value); if (map.containsKey(key)) { cache.remove(map.get(key)); } else if (cap == cache.size()) { Node last = cache.removeLast(); map.remove(last.key); } cache.addFirst(node); map.put(key, node); } }