• LeetCode 146. LRU 缓存机制


     

     

    思路

    哈希表 + 双向链表。在面试中,面试官一般会期望读者能够自己实现一个简单的双向链表,而不是使用语言自带的、封装好的数据结构。
     

    方法一:哈希表 + C++自带的双向链表 list

     1 struct Node {
     2     int key;
     3     int value;
     4     Node(){}
     5     Node(int _key,int _value): key(_key), value(_value){}
     6 };
     7 
     8 class LRUCache {
     9 private:
    10     int capacity;
    11     list<Node*> cache;
    12     unordered_map<int, list<Node*>::iterator> mp;
    13 public:
    14     LRUCache(int capacity) {
    15         this->capacity = capacity;
    16     }
    17     
    18     int get(int key) {
    19         if(mp.find(key) != mp.end()) {
    20             //将其更新到队头
    21             Node* node = *(mp[key]);
    22             cache.erase(mp[key]);
    23             cache.push_front(node);
    24             mp[key] = cache.begin();
    25 
    26             //返回对应的值    
    27             return node->value;
    28         } else {
    29             return -1;
    30         }
    31     }
    32     
    33     void put(int key, int value) {
    34         if(mp.find(key) != mp.end()) {
    35             Node* node = *(mp[key]);
    36             cache.erase(mp[key]);
    37             node->value = value; 
    38             cache.push_front(node);
    39             mp[key] = cache.begin();
    40         } else {
    41             Node* node = new Node(key, value);
    42             cache.push_front(node);
    43             mp[key] = cache.begin();
    44             if(cache.size() > capacity) {
    45                 mp.erase(cache.back()->key);
    46                 cache.pop_back();
    47             }
    48         }
    49     }
    50 };
    51 
    52 /**
    53  * Your LRUCache object will be instantiated and called as such:
    54  * LRUCache* obj = new LRUCache(capacity);
    55  * int param_1 = obj->get(key);
    56  * obj->put(key,value);
    57  */

    复杂度分析

    时间复杂度:get和put都是O(1)。

    方法二:哈希表 + 自己实现的简单双向链表

     

     1 struct DLinkedNode {
     2     int key, value;
     3     DLinkedNode* prev;
     4     DLinkedNode* next;
     5     DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}
     6     DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
     7 };
     8 
     9 class LRUCache {
    10 private:
    11     unordered_map<int, DLinkedNode*> cache;
    12     DLinkedNode* head;
    13     DLinkedNode* tail;
    14     int size;
    15     int capacity;
    16 
    17 public:
    18     LRUCache(int _capacity): capacity(_capacity), size(0) {
    19         // 使用伪头部和伪尾部节点
    20         head = new DLinkedNode();
    21         tail = new DLinkedNode();
    22         head->next = tail;
    23         tail->prev = head;
    24     }
    25     
    26     int get(int key) {
    27         if (!cache.count(key)) {
    28             return -1;
    29         }
    30         // 如果 key 存在,先通过哈希表定位,再移到头部
    31         DLinkedNode* node = cache[key];
    32         moveToHead(node);
    33         return node->value;
    34     }
    35     
    36     void put(int key, int value) {
    37         if (!cache.count(key)) {
    38             // 如果 key 不存在,创建一个新的节点
    39             DLinkedNode* node = new DLinkedNode(key, value);
    40             // 添加进哈希表
    41             cache[key] = node;
    42             // 添加至双向链表的头部
    43             addToHead(node);
    44             ++size;
    45             if (size > capacity) {
    46                 // 如果超出容量,删除双向链表的尾部节点
    47                 DLinkedNode* removed = removeTail();
    48                 // 删除哈希表中对应的项
    49                 cache.erase(removed->key);
    50                 // 防止内存泄漏
    51                 delete removed;
    52                 --size;
    53             }
    54         }
    55         else {
    56             // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
    57             DLinkedNode* node = cache[key];
    58             node->value = value;
    59             moveToHead(node);
    60         }
    61     }
    62 
    63     void addToHead(DLinkedNode* node) {
    64         node->prev = head;
    65         node->next = head->next;
    66         head->next->prev = node;
    67         head->next = node;
    68     }
    69     
    70     void removeNode(DLinkedNode* node) {
    71         node->prev->next = node->next;
    72         node->next->prev = node->prev;
    73     }
    74 
    75     void moveToHead(DLinkedNode* node) {
    76         removeNode(node);
    77         addToHead(node);
    78     }
    79 
    80     DLinkedNode* removeTail() {
    81         DLinkedNode* node = tail->prev;
    82         removeNode(node);
    83         return node;
    84     }
    85 };

    复杂度分析

    时间复杂度:对于 put 和 get 都是 O(1)。

    空间复杂度:O(capacity),因为哈希表和双向链表最多存储 capacity + 1个元素。

  • 相关阅读:
    关于Java集合框架,这篇讲的还算不错了,建议大家看看!
    其实SQL优化调优,就跟吃饭喝水一样简单,教你抓住SQL的本质!
    深度分析ReentrantLock源码及AQS源码,从入门到入坟,建议先收藏!
    建议收藏,从零开始创建一个Activiti工作流,手把手教你完成
    这个厉害了,ssm框架整合全过程,建议收藏起来好好看看
    阿里技术专家深入讲解,SpringMVC入门到进阶,看这一篇就够了
    python3.6:AttributeError: 'generator' object has no attribute 'next'
    【转】modulenotfounderror: no module named 'matplotlib._path'问题的解决
    sublime中使用插件anaconda而在代码中出现方框
    Linux上用sublime编辑Python时候出现"SyntaxError: Non-ASCII character ‘xe5′ in file"的问题
  • 原文地址:https://www.cnblogs.com/FengZeng666/p/14420193.html
Copyright © 2020-2023  润新知