本题是leetcode,地址:146. LRU缓存机制java
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持如下操做: 获取数据 get 和 写入数据 put 。node
获取数据 get(key) - 若是关键字 (key) 存在于缓存中,则获取关键字的值(老是正数),不然返回 -1。
写入数据 put(key, value) - 若是关键字已经存在,则变动其数据值;若是关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据以前删除最久未使用的数据值,从而为新的数据值留出空间。算法进阶:缓存
你是否能够在 O(1) 时间复杂度内完成这两种操做?数据结构
示例:this
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );设计
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操做会使得关键字 2 做废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操做会使得关键字 1 做废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4code
LRU 算法其实是让你设计数据结构:首先要接收一个 capacity 参数做为缓存的最大容量,而后实现两个 API,一个是 put(key, val) 方法存入键值对,另外一个是 get(key) 方法获取 key 对应的 val,若是 key 不存在则返回 -1。ci
注意哦,get 和 put 方法必须都是 O(1)O(1) 的时间复杂度,在双向链表的实现中,使用一个伪头部(dummy head)和伪尾部(dummy tail)标记界限,这样在添加节点时添加到头节点,删除时,删除尾节点的数据。leetcode
class LRUCache { class MyNode { int key; int value; MyNode prev; MyNode next; public MyNode() { } public MyNode(int _key, int _value) { key = _key; value = _value; } } private int capacity; private int size; private Map<Integer, MyNode> cache = new HashMap<>(); private MyNode head, tail; public LRUCache(int capacity) { this.size = 0; this.capacity = capacity; this.head = new MyNode(); this.tail = new MyNode(); head.next = tail; tail.prev = head; } public int get(int key) { MyNode node = cache.get(key); if (node == null) { return -1; } else { // 更换到头节点 moveToHead(node); return node.value; } } private void moveToHead(MyNode node) { removeNode(node); addToHead(node); } public void put(int key, int value) { MyNode node = cache.get(key); if (node == null) { node = new MyNode(key, value); addToHead(node); size++; if (size > capacity) { MyNode tail = removeTail(); cache.remove(tail.key); size--; } cache.put(key,node); } else { node.value = value; moveToHead(node); } } private void addToHead(MyNode node) { node.prev = head; node.next = head.next; head.next.prev = node; head.next = node; } private MyNode removeTail() { MyNode node = tail.prev; removeNode(node); return node; } private void removeNode(MyNode node) { node.prev.next = node.next; node.next.prev = node.prev; } } /** * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); */