zoukankan      html  css  js  c++  java
  • [LeetCode] 146. LRU Cache

    1. 原题链接:https://leetcode.com/problems/lru-cache/

    2. 解题思路

    1. 为了增删改查都有较高的性能,使用双向链表和哈希表的组合
    2. 针对LRU,哈希表对于查询和修改可以实现O(1)的时间复杂度,但是无法在O(1)时间复杂度实现删除操作
    3. 双向链表可以很好的实现O(1)时间复杂度的增加和删除,因此需要将双向链表和哈希表结合起来一起使用,这两种数据结构的结合点在于哈希表的value存储的是双向链表某个节点的地址(也就是:哈希表的value是一个指向双向链表某个节点的指针)
    4. 越靠近双向链表头部的节点,表示你最近刚访问过,越靠近双向链表尾部的节点,表示最近很少访问,最后一个节点表示最近访问最少

    3. 算法

    1. 对于get操作,如果节点存在将其从当前位置摘除,并将该节点插入到链表头部;否则,返回-1
    2. 对于put操作,如果key存在,更新value;否则,检查当前capacity是否已满,如果已满,删除最后一个节点(也就是:最近最少访问的节点)和哈希表对应的key;然后,创建包含key、value的新节点,将其插入链表头部

    4. 实现

    struct Node {
        int key; //为了删除节点时,同时删除hash表中的key
        int val;
        Node *next;
        Node *prev;
        Node(int k, int v){
            key = k;
            val = v;
            next = NULL;
            prev = NULL;
        }
    };
    
    class LRUCache {
    public:
        LRUCache(int capacity) {
            size = capacity;
            //哑节点可以化解很多异常情况
            Node *dummy1 = new Node(-1, -1);
            Node *dummy2 = new Node(-1, -1);
            head = dummy1;
            tail = dummy2;
            head->next = dummy2;
            tail->prev = dummy1;
        }
    
        int get(int key) {
            map<int, Node*>::iterator iter;
            iter = table.find(key);
            if(iter != table.end()){
                Node *cur = iter->second;
                //从当前位置摘掉
                cur->prev->next = cur->next;
                cur->next->prev = cur->prev;
                //将该节点插入头部
                cur->next = head->next;
                cur->prev = head;
                head->next->prev = cur;
                head->next = cur;
                return cur->val;
            }
            return -1;
        }
    
        void put(int key, int value) {
            if(get(key) > 0){
                //更新已存在key的value
                // head->next->val = value;
                table[key]->val = value;
                return;
            }
    
            //当容量为0时,先删除,再插入
            if(size == 0){
                Node *del_node = tail->prev;
                del_node->next->prev = del_node->prev;
                del_node->prev->next = del_node->next;
                del_node->prev = NULL;
                del_node->next = NULL;
                //先删除hash表中的key,再删除节点
                table.erase(del_node->key);
                delete del_node;
                size++;
            }
            Node *node = new Node(key, value);
            //将其插入头部
            node->next = head->next;
            node->prev = head;
            head->next->prev = node;
            head->next = node;
            table[key] = node;
            size--;
        }
    
    private:
        map<int, Node*> table;
        int size;
        Node *head;
        Node *tail;
    };
    
  • 相关阅读:
    tomcat内存调优
    loadrunner 商城项目随机选书
    loadrunner 脚本调试之添加日志
    Macaca自动化测试工具环境搭建
    python selenium 自动化测试图片识别1
    SQL——数据插入
    SQL集合操作
    SQL——多表查询
    SQL简单查询操作
    PV操作——实力模型2
  • 原文地址:https://www.cnblogs.com/wengle520/p/12336341.html
Copyright © 2011-2022 走看看