LRU Cache

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(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.

The cache is initialized with a positive capacity.

Follow up:
Could you do both operations in O(1) time complexity?

Example:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4
分析:
因为要把least recently used item在container满了的时候移除掉,所以,我们需要有一个list来mantain这样一个order
同时,因为要取数,所以可以用map来保存数与item的关系。
 1 class Node {
 2     int key, value;
 3     Node pre, next;
 4 
 5     public Node(int key, int value) {
 6         this.key = key;
 7         this.value = value;
 8     }
 9 }
10 
11 public class LRUCache {
12     HashMap<Integer, Node> map;
13     int capicity;
14     Node head, tail;
15     
16     public LRUCache(int capacity) {
17         this.capicity = capacity;
18         map = new HashMap<>();
19         head = new Node(0, 0);
20         tail = new Node(0, 0);
21         head.next = tail;
22         tail.pre = head;
23     }
24 
25     public void deleteNode(Node node) {
26         node.pre.next = node.next;
27         node.next.pre = node.pre;
28     }
29 
30     public void addToHead(Node node) {
31         node.next = head.next;
32         node.next.pre = node;
33         node.pre = head;
34         head.next = node;
35     }
36 
37     public int get(int key) {
38         if (map.get(key) != null) {
39             Node node = map.get(key);
40             deleteNode(node);
41             addToHead(node);
42             return node.value;
43         }
44         return -1;
45     }
46 
47     public void put(int key, int value) {
48         if (map.get(key) != null) {
49             Node node = map.get(key);
50             node.value = value;
51             deleteNode(node);
52             addToHead(node);
53         } else {
54             Node node = new Node(key, value);
55             map.put(key, node);
56             if (map.size() > capicity) {
57                 map.remove(tail.pre.key);
58                 deleteNode(tail.pre);
59             }
60             addToHead(node);
61         }
62     }
63 }

一种不带dummy head and tail的情况。

 1 public class LRUCache {
 2     private int cacheSize;
 3     private HashMap<Integer, Entry> map;// 缓存容器
 4     private Entry first;// 链表头
 5     private Entry last;// 链表尾
 6 
 7     public LRUCache(int capacity) {
 8         cacheSize = capacity;
 9         map = new HashMap<>();
10     }
11 
12     public int get(int key) {
13         Entry node = map.get(key);
14         if (node != null) {
15             moveToHead(node);
16             return node.value;
17         } else {
18             return -1;
19         }
20     }
21 
22     private void moveToHead(Entry node) {
23         if (first == null) {
24             first = node;
25             last = node;
26             return;
27         }
28         if (node == first) return;
29         if (node.prev != null) node.prev.next = node.next;
30         if (node.next != null) node.next.prev = node.prev;
31         if (node == last) last = node.prev;
32         
33         node.next = first;
34         node.prev = null;
35         first.prev = node;
36         first = node;
37     }
38     
39     public void remove(int key) {
40         Entry node = map.get(key);
41         if (node != null) {
42             if (node.prev != null) node.prev.next = node.next;
43             if (node.next != null) node.next.prev = node.prev;
44             if (last == node) last = node.prev;
45             if (first == node) first = node.next;
46         }
47         map.remove(key);
48     }
49 
50     public void put(int key, int value) {
51         Entry node = map.get(key);
52         if (node == null) {
53             if (map.size() >= cacheSize) {
                   // remove the last entry
54 map.remove(last.key); 55 if (last.prev != null) { 56 last.prev.next = null; 57 } else { 58 first = null; 59 } 60 last = last.prev; 61 } 62 node = new Entry(key, value); 63 } 64 node.value = value; 65 map.put(key, node); 66 moveToHead(node); 67 } 68 } 69 70 class Entry { 71 Entry prev; 72 Entry next; 73 int value; 74 int key; 75 76 public Entry(int key, int value) { 77 this.key = key; 78 this.value = value; 79 } 80 }

 

posted @ 2016-07-15 22:48  北叶青藤  阅读(373)  评论(0编辑  收藏  举报