LeetCode 之 LRU Cache解决思路
2014-06-24 15:56
435 查看
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations:
这道题主要是实现“最近最少使用替换”算法。
Cache的大小是有限的,当增加新的值时,如果没有额外空间,就需要采用替换算法。替换算法的核心就是要维护一个状态,即:哪个值应该被替换出去,哪个值是最新的。
同时当调用get方法时,需要更新刚索引过的值,将其状态设置为最新,再更新其他值的状态,最近最少使用的那个值将更新为:下次被替换出去。set方法同样需要更新各个值的状态。
根据上述的分析,我们可以采用单向链表来实现该替换算法。该链表需要维护一个尾指针。我们将最新状态的值放置在尾部,最近最少使用的值放在头部。当没有额外空间时,加入新值,我们在尾部添加,同时删除头部的旧值。当更新值得状态时,对应的操作就是链表的删除和插入操作。
但是链表的缺点就是遍历耗时。如何在O(1)时间内访问到链表中的值呢?可以结合Hash表的性质。hash表内存储节点的key值和节点的指针。当调用get方法时,利用hashMap获取到包含该key的节点,时间为O(1)。此时,需要做的就是要维护hashmap和链表的一致性。
getand
set.
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 之 Flatten Binary Tree to Linked List 解决思路
- leetcode之 wordBreak(1)解决思路
- 【LeetCode】LRU Cache 解决报告
- 两种回溯方法解决子集问题的思路 leetcode 78. Subsets
- [LeetCode] 116. Populating Next Right Pointers in Each Node 解决思路
- [LeetCode]LRU Cache有个问题,求大神解答【已解决】
- [LeetCode] 57. Insert Interval 解决思路
- leetcode Two Sum 解决思路
- LeetCode之 Reorder List解决思路
- leetcode:Sort List 使用归并排序的解决思路
- [LeetCode] 35. Search Insert Position 解决思路
- [leetcode53]两种思路解决的Maximun Subarray
- 关于刷新重复提交的一种解决思路
- 用 OpenSessionInViewInterceptor 的思路解决 Spring框架中的Hibernate Lazy
- 正确而优美的解决logout问题的思路
- 项目统一开发管理解决方案思路[项目组成员同时做很多项目的解决思路探讨]
- 项目统一开发管理解决方案思路[项目组成员同时做很多项目的解决思路探讨]
- 连接池已满问题解决思路
- Log actively being archived by another process的问题解决思路