• LeetCode 146. LRU Cache


    原题链接在这里:https://leetcode.com/problems/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.

    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

    题解:

    可以通过HashMap 和 Double LinkedList来完成。每个key, value用一个Node 来储存,按照添加顺序一个一个放在list 的head后面。同时把<key, node>放在HashMap中。

    get时看HashMap中是否有这个key, 有的话就找到对应的node, 在node里取出对应的value. 同时更新该node 在list中的位置。

    set时分三种情况:1. 看HashMap中是否有这个key, 有的话说明本来就有这个key对应的node, 只需要把原有node的value更改并且更新该node 在list中位置即可。

    2. HashMap中没有这个key, 同时HashMap的size未达到capacity, 那么新建一个node, 加入HashMap 和 list中即可。

    3. HashMap中没有这个key, 同时HashMap的size已经等于capacity, 多加就要溢出,所以按照2中完成添加后要从HashMap 和 list中都去掉最老的node.

    Time Complexity: get, O(1). put O(1).

    Space: O(n).

    AC Java:

     1 class Node{
     2     Node prev;
     3     Node next;
     4     int key;
     5     int value;
     6     Node(int key, int value){
     7         this.key = key;
     8         this.value = value;
     9     }
    10 }
    11 
    12 public class LRUCache {
    13     Node head;
    14     Node tail;
    15     int capacity;
    16     HashMap<Integer, Node> hm;
    17     
    18     public LRUCache(int capacity) {
    19         head = new Node(-1,-1);
    20         tail = new Node(1,1);
    21         head.next = tail;
    22         tail.prev = head;
    23         this.capacity = capacity;
    24         hm = new HashMap<Integer, Node>();
    25     }
    26     
    27     public int get(int key) {
    28         if(hm.containsKey(key)){
    29             Node p = hm.get(key); //error
    30             putToHead(p);   //put p to the newest position of list
    31             return p.value;
    32         }
    33         return -1;
    34     }
    35     
    36     public void set(int key, int value) {
    37         if(hm.containsKey(key)){
    38             Node p = hm.get(key);
    39             p.value = value;
    40             putToHead(p);   //update p's position in the list
    41         }else if(hm.size() < capacity){
    42             Node p = new Node(key, value);
    43             hm.put(key,p);
    44             putToHead(p);
    45         }else{
    46             Node p = new Node(key,value);
    47             hm.put(key,p);
    48             putToHead(p);
    49             int oldKey = removeOldest();    //remove oldest node from the list
    50             hm.remove(oldKey);  //remove oldest node from hashmap
    51         }
    52     }
    53     
    54     private void putToHead(Node p){
    55         if(p.prev != null && p.next != null){
    56             p.prev.next = p.next;
    57             p.next.prev = p.prev;
    58         }
    59         p.prev = head;
    60         p.next = head.next;
    61         head.next.prev = p;
    62         head.next = p;
    63     }
    64     
    65     private int removeOldest(){
    66         Node oldest = tail.prev;
    67         int oldKey = oldest.key;
    68         oldest.prev.next = tail;
    69         tail.prev = oldest.prev;
    70         return oldKey;
    71     }
    72 }

    另一种方法是用LinkedHashMap, 这种数据结构本身已经把HashMap按照添加顺序放好了。

    可以参见这个网页:http://www.tutorialspoint.com/java/java_linkedhashmap_class.htm 

    所以实现起来很简洁,get时需要更新位置,更新位置是通过删掉旧的,复制一下加回去。

    set时参照上面的三种情况即可。

    AC Java:

     1 import java.util.LinkedHashMap;
     2 public class LRUCache {
     3     LinkedHashMap<Integer, Integer> linkedHM;
     4     int capacity;
     5     public LRUCache(int capacity) {
     6         linkedHM = new LinkedHashMap<Integer, Integer>();
     7         this.capacity = capacity;
     8     }
     9     
    10     public int get(int key) {
    11         if(linkedHM.containsKey(key)){
    12             int val = linkedHM.get(key);
    13             linkedHM.remove(key);
    14             linkedHM.put(key,val);
    15             return val;
    16         }
    17         return -1;
    18     }
    19     
    20     public void set(int key, int value) {
    21         if(linkedHM.containsKey(key)){
    22             linkedHM.remove(key);
    23             linkedHM.put(key,value);
    24         }else if(linkedHM.size() < capacity){
    25             linkedHM.put(key,value);
    26         }else{
    27             int oldKey = linkedHM.keySet().iterator().next();
    28             linkedHM.remove(oldKey);
    29             linkedHM.put(key,value);
    30         }
    31     }
    32 }
  • 相关阅读:
    买书问题
    结队开发项目—NABC模型
    《梦断代码》读后感3
    <梦断代码>读后感2
    四则运算3
    数组结对开发
    BICEP单元测试——随机四则运算升级版
    新 四则运算题目 修改
    新 四则运算题目 C++
    新 四则运算题目设计思路
  • 原文地址:https://www.cnblogs.com/Dylan-Java-NYC/p/4935048.html
Copyright © 2020-2023  润新知