LeetCode 之 LRU Cache解决思路
来源:互联网 发布:频谱仪软件 编辑:程序博客网 时间:2024/04/30 00:21
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations:get
andset
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.set(key, value)
- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
这道题主要是实现“最近最少使用替换”算法。
Cache的大小是有限的,当增加新的值时,如果没有额外空间,就需要采用替换算法。替换算法的核心就是要维护一个状态,即:哪个值应该被替换出去,哪个值是最新的。
同时当调用get方法时,需要更新刚索引过的值,将其状态设置为最新,再更新其他值的状态,最近最少使用的那个值将更新为:下次被替换出去。set方法同样需要更新各个值的状态。
根据上述的分析,我们可以采用单向链表来实现该替换算法。该链表需要维护一个尾指针。我们将最新状态的值放置在尾部,最近最少使用的值放在头部。当没有额外空间时,加入新值,我们在尾部添加,同时删除头部的旧值。当更新值得状态时,对应的操作就是链表的删除和插入操作。
但是链表的缺点就是遍历耗时。如何在O(1)时间内访问到链表中的值呢?可以结合Hash表的性质。hash表内存储节点的key值和节点的指针。当调用get方法时,利用hashMap获取到包含该key的节点,时间为O(1)。此时,需要做的就是要维护hashmap和链表的一致性。
import java.util.HashMap;public class LRUCache { private LinkList list; public LRUCache(int capacity) { list = new LinkList(capacity); } public int get(int key) { return list.get(key); } public void set(int key, int value) { list.set(key, value); } public void print(){ list.printList(); }class LinkList{ private int capacity;//链表总长度 private int size;//当前链表节点个数 private Node head;//头指针 private Node tail;//尾指针 private HashMap<Integer, Node> map; public LinkList(int capacity){ this.capacity = capacity; this.size = 0; head = new Node(); tail = head; tail.next = null; map = new HashMap<Integer,Node>(capacity); } public int get(int key){ int val = -1; if(map.containsKey(key)){ Node node = map.get(key); val = node.value; this.update(node);//更新链表和hashmap状态 return val; }else{ return val; } } public void set(int key, int value){ if(map.containsKey(key)){ Node node = map.get(key); node.value = value; this.update(node); }else{ Node node = new Node(key, value);node.next = null;tail.next = node;tail = node;map.put(key, node); if(size < capacity){ size++; }else{ Node p = head.next; int k = p.key; head.next = p.next; p.next = null; p = null; map.remove(k); } } } //当调用get和set方法时,当前节点应该需要置于最新状态,即将该节点放置到链表的尾部。采用的是单向链表,节点的删除需要从头遍历链表到当前节点的前一个节点,时间//时间复杂度为O(n),这里采用O(1)的时间复杂度删除节点p。//交换节点p和p.next的值,此时删除p.next,即将该节点插入到尾部即可。但需要注意的是在hashmap中就要将p.key和p.next.key的节点交换一下,否则hashmap维护的节点//就是错误的了。 public void update(Node p){ if(p != tail){ Node p2 = p.next; map.put(p.key, p2);//更新hashmap中的节点 map.put(p2.key, p);//更新hashmap中的节点 int temp = p.key; p.key = p2.key; p2.key = temp; temp = p.value; p.value = p2.value; p2.value = temp; if(p2 != tail){ p.next = p2.next; p2.next = null; tail.next = p2; tail = p2; } } } public void printList(){ Node p = head.next; while(p != null){ System.out.print(p.key +"->" + p.value + ","); p = p.next; } System.out.println(); }}class Node{ int key; int value; Node next; public Node(){ } public Node(int key, int value){ this.key = key; this.value = value; }}
- LeetCode 之 LRU Cache解决思路
- leetcode之LRU Cache
- leetcode之LRU Cache
- Leetcode之LRU Cache
- Leetcode之LRU Cache
- leetcode之LRU Cache
- LeetCode OJ 之 LRU Cache(LRU缓存)
- LeetCode LRU 缓存 LRU Cache
- LRU Cache | leetcode
- Leetcode: LRU Cache
- LeetCode:LRU Cache
- Leetcode: LRU Cache
- [LeetCode] LRU Cache
- [LeetCode]LRU Cache
- [LeetCode] LRU Cache
- leetcode LRU Cache
- LeetCode题解:LRU Cache
- LeetCode | LRU Cache
- 不打扰是我最后的温柔
- NHibernate的SessionContext
- boost 系列三 lexical_cast
- 生产者和消费者(二)
- android图片缓存框架Android-Universal-Image-Loader
- LeetCode 之 LRU Cache解决思路
- showModalDialog url为struts action 第一次打开可以调用action 第二次以后不可以 原因是
- AngularJS:何时应该使用Directive、Controller、Service?
- Js 倒计时器
- Linq where示例
- 香港到武汉
- 用模态对话框实现加减乘除
- VC++实现一张图片循环滚动
- 转载: 进程与线程的一个简单解释