leetcode -- LRU Cache

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and 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.

[解题思路]

LRU是Least Recently Used 的缩写,翻译过来就是“最不常使用”,也就是说,LRU缓存把最不常使用的数据移除,让给最新读取的数据。大多数情况下,最常读取的,也是读取次数最多的,所以,利用LRU缓存,我们能够提高系统的performance. LRU cache是非常频繁出现的一道面试题,一般来讲,当我们问到这道题时,面试官往往想得到的答案是利用 doubly linked list + hashtable 实现 LRU Cache, 那么我们现在就来讲一讲如何利用doubly linked list + hashtable实现LRU Cache的。

这里为什么使用Doubly linkd list 而不使用 Linked list的原因是:

当访问一个节点后,我们需要将他从原来的list中删除,然后将它插入到头节点处,删除过程中需要将其前后节点连接起来,单链表做不到。

查询:

  • 根据键值查询hashmap,若命中,则返回节点,否则返回null。
  • 从双向链表中删除命中的节点,将其重新插入到表头。
  • 所有操作的复杂度均为O(1)。

插入:

  • 将新的节点关联到Hashmap
  • 如果Cache满了,删除双向链表的尾节点,同时删除Hashmap对应的记录
  • 将新的节点插入到双向链表中头部

更新:

  • 和查询相似

删除:

  • 从双向链表和Hashmap中同时删除对应的记录。
 1 public class LRUCache {
 2     
 3     private int capacity;
 4     private Map<Integer, Entry> nodes;
 5     private int currentSize;
 6     private Entry first;
 7     private Entry last;
 8     
 9     public LRUCache(int capacity) {
10         this.capacity = capacity;
11         currentSize = 0;
12         nodes = new HashMap<Integer, Entry>();
13     }
14     
15     public int get(int key) {
16         Entry node = nodes.get(key);
17         if(node != null){
18             moveToHead(node);
19             return node.value;
20         } else {
21             return -1;
22         }
23     }
24     
25     public void set(int key, int value) {
26         Entry node = nodes.get(key);
27         if(node == null){
28             if(currentSize >= capacity){
29                 nodes.remove(last.key);
30                 removeLast();
31             } else {
32                 currentSize ++;
33             }
34             node = new Entry();
35         }
36         
37         if(currentSize == 1){
38             first = node;
39             last = node;
40         }
41         
42         node.key = key;
43         node.value = value;
44         moveToHead(node);
45         nodes.put(key, node);
46     }
47     
48     private void moveToHead(Entry node){
49         if(node == first)
50             return;
51         
52         // delete current node from doubly linked list
53         if(node.pre != null){
54             node.pre.next = node.next;
55         }
56         if(node.next != null){
57             node.next.pre = node.pre;
58         }
59         
60         if(last == node){
61             last = node.pre;
62         }
63         
64         if(first != null){
65             node.next = first;
66             first.pre = node;
67         }
68         first = node;
69         node.pre = null;
70         
71     }
72     
73     private void removeLast(){
74         if(last != null){
75             if(last.pre != null){
76                 last.pre.next = null;
77             } else {
78                 first = null;
79             }
80             last = last.pre;
81         }
82     }
83 }
84 
85 class Entry{
86     Entry pre;
87     Entry next;
88     int key;
89     int value;
90 }
原文地址:https://www.cnblogs.com/feiling/p/3426967.html