21.03.14 LeetCode146. LRU 缓存机制

运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制 。
实现 LRUCache 类:

LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
 

进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作?

 

示例:

输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4

 1 class LRUCache {
 2     //先自己实现双向链表,包括方法add2head/removeNode/move2head/removeTail
 3     class DoubleLinkedNode
 4     {
 5         int key;
 6         int value;
 7         DoubleLinkedNode pre;
 8         DoubleLinkedNode next;
 9         public DoubleLinkedNode(){}
10         public DoubleLinkedNode(int key,int value){this.key = key;this.value = value;}
11     }
12     //使用哈希表存储key对应的链表节点,节点内存放value值
13     private Map<Integer,DoubleLinkedNode> cache;
14     private int size;
15     private int capacity;
16     private DoubleLinkedNode head,tail;
17     public LRUCache(int capacity) {
18         this.size = 0;
19         this.capacity = capacity;
20         cache = new HashMap<Integer,DoubleLinkedNode>();
21         //伪头部和伪尾部
22         head = new DoubleLinkedNode();
23         tail = new DoubleLinkedNode();
24         head.next = tail;
25         tail.pre = head;
26     }
27     
28     public int get(int key) {
29         //查找key有无位于双向链表中,有则返回关键字的值
30         DoubleLinkedNode node = cache.get(key);
31         if(node==null)
32             return -1;
33         else{
34             move2head(node);
35             return node.value;
36         }
37     }
38     
39     public void put(int key, int value) {
40         DoubleLinkedNode tep = cache.get(key);
41         if(tep == null)
42         {
43             //key不存在
44             //新建节点
45             DoubleLinkedNode node = new DoubleLinkedNode(key,value);
46             //当缓存容量达到上限
47             if(size==capacity)
48             {
49                 //删除尾结点
50                 cache.remove(removeTail().key);
51                 size--;
52             }
53             //添加进哈希表
54             cache.put(key,node);
55             //添加进链表头部
56             add2head(node);size++;
57             
58         }
59         else{
60             //key已存在,变更其数据值
61             tep.value = value;
62             //刚使用过,所以放在链表头部
63             move2head(tep);
64         }
65     }
66     private void add2head(DoubleLinkedNode node)
67     {
68         node.pre = head;
69         node.next = head.next;
70         head.next.pre = node;
71         head.next = node;
72     }
73     private void removeNode(DoubleLinkedNode node)
74     {
75         node.pre.next = node.next;
76         node.next.pre = node.pre;
77     }
78     private void move2head(DoubleLinkedNode node)
79     {
80         //移动当前节点至头结点
81         removeNode(node);
82         add2head(node);
83     }
84     private DoubleLinkedNode removeTail()
85     {
86         DoubleLinkedNode rem = tail.pre;
87         removeNode(rem); 
88         return rem;
89     }
90 }

 

posted @ 2021-03-14 14:51  γGama  阅读(52)  评论(0编辑  收藏  举报