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.

Ref: http://www.cnblogs.com/feiling/p/3426967.html

[解题思路]

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     private DoubleLinkNode first;
     3     private DoubleLinkNode last;
     4     private int capacity;
     5     private int currentSize;
     6     private HashMap<Integer, DoubleLinkNode> nodesMap;
     7     
     8     
     9     public LRUCache(int capacity){
    10         this.capacity = capacity;
    11         currentSize = 0;
    12         nodesMap = new HashMap<Integer, DoubleLinkNode>();
    13         
    14     }
    15     
    16     public int get(int key){
    17         DoubleLinkNode node = nodesMap.get(key);
    18         if(node != null){
    19             moveToHead(node);
    20             return node.value;
    21         }else{
    22             return -1;
    23         }
    24     }
    25     
    26     public void set(int key, int value){
    27         DoubleLinkNode node = nodesMap.get(key);
    28         if(node == null){
    29             if(currentSize >= capacity){
    30                 nodesMap.remove(last.key);
    31                 removeLast();
    32             }else{
    33                 currentSize++;
    34             }
    35             node = new DoubleLinkNode();
    36         }
    37         
    38         if(currentSize == 1){
    39             first = node;
    40             last = node;
    41         }
    42         
    43         node.key = key;
    44         node.value = value;
    45         moveToHead(node);
    46         nodesMap.put(key,node);
    47     }
    48     
    49     private void moveToHead(DoubleLinkNode node){
    50             if(node == first)
    51                 return;
    52             
    53             if(last == node){
    54                 last = node.front;
    55             }
    56              // delete current node from doubly linked list
    57             if(node.front != null){
    58                 node.front.back = node .back;
    59             }
    60             
    61             if(node.back != null){
    62                 node.back.front = node.front;
    63             }
    64             
    65             if(first != null){
    66                 node.back = first;
    67                 first.front = node;
    68             }
    69             
    70             first = node;
    71             node.front = null;
    72     }
    73     
    74     private void removeLast(){
    75         if(last != null){
    76             if(last.front != null){
    77                 last.front.back = null;
    78             }else{
    79                 first = null;
    80             }
    81             last = last.front;
    82         }
    83     }   
    84 }
    85 
    86 class DoubleLinkNode{
    87     DoubleLinkNode front;
    88     DoubleLinkNode back;
    89     int key;
    90     int value;
    91 }
原文地址:https://www.cnblogs.com/RazerLu/p/3555330.html