LeetCode 146 LRU算法-hash+双链表、unorder_map

 第一种解法:hash+双向链表

struct Node{
    int key;
    int val;
    struct Node* left;
    struct Node* right;
    Node(int _key, int _val) : key(_key), val(_val), left(nullptr), right(nullptr){}
};//链表结点的数据格式

class LRUCache {
private:
    int cap;//LRU的容量
    //无序的hash表,key int, value Node* 对应的双向链表中的结点,O(1)直接找到Node
    unordered_map<int, struct Node*> hash;//使用map也没问题
    struct Node* head;//头指针
    struct Node* tail;//尾指针
    //删除指定结点p
    void remove(struct Node* p)
    {
        p->left->right = p->right;
        p->right->left = p->left;
    }
    //头插法,也可以采用尾插法
    void insert(struct Node* p)
    {
        p->right = head->right;
        p->left = head;
        head->right->left = p;//顺序不可以搞错!!!
        head->right = p;
    }
public:
    //构造函数,初始化
    LRUCache(int capacity) {
        this->cap = capacity;
        head = new Node(-1, -1);
        tail = new Node(-1, -1);
        head->right = tail;
        tail->left = head;
    }
    // get key
    int get(int key) {
        // 如果key count为0,说明不存在
        if(hash.count(key) == 0) return -1;
        auto p = hash[key];
        remove(p);//先删除p
        insert(p);//把p放在头部
        return p->val;
    }

    void put(int key, int val) {
        //key存在于hash表中,更新key的位置,更新key对应的Node结点值
        if(hash.count(key) != 0)
        {
            auto p = hash[key];
            remove(p);
            insert(p);
            p->val = val;
            return;
        }
        //新插入的结点,此时LRUcache已满
        if(hash.size() >= cap)
        {
            struct Node* p = tail->left;
            remove(p);//删除尾结点
            hash.erase(p->key);//删除hash表中对应的key
            delete p;//记得释放
        }
        struct Node* tmp = new Node(key,val);//创建新的结点
        hash[key] = tmp;//放入hash表
        insert(tmp);//插入链表中
    }
};

 第二种解法:利用unordered_map本身进行匹配,实验表明,unordered_map是头插法,并且没有rbegin()迭代器,使用end()达不到想要的效果,所以每次删除数据冷的结点,需要遍历整个hash表,到第17个case通过不了

private:
    int cap;
    unordered_map<int, int> hash;
    //使某个key的键值对放在hash表最前边
    void makeRecently(int key)
    {
        int val = hash[key];
        hash.erase(key);
        hash[key] = val;
    }
public:
    LRUCache(int capacity) {
        this->cap = capacity;
    }
    
    int get(int key) {
        if(hash.find(key) == hash.end())
            return -1;
        makeRecently(key);
        return hash[key];
    }
    
    void put(int key, int value) {
        if(hash.find(key) != hash.end())
        {
            hash[key] = value;
            makeRecently(key);
            return;
        }
        if(hash.size() >= this->cap)
        {
            auto tail = hash.begin();
            for(auto iter = hash.begin(); iter != hash.end(); iter++)
                tail = iter;
            int oldestKey = tail->first;
            hash.erase(oldestKey);
            //hash.erase(tail);  //erase参数可以是key或者迭代器
        }
        hash[key] = value;
        return;
    }
};

两年前的解法:

class LRUCache {
public:

    struct Node{
        int key;
        int value;
        Node* left;
        Node* right;
        Node(int _key, int _value): key(_key),value(_value),left(NULL),right(NULL){}
    }*L, *R;
    int n;
    unordered_map<int, Node*> hash;
    void remove(Node* p)
    {
        p->left->right = p->right;
        p->right->left = p->left;
    }
    void insert(Node* p)//插在头部
    {
        p->left = L;
        p->right = L->right;
        L->right->left = p;
        L->right = p;
        /*L->right = p;顺序千万别乱
        L->right->left = p;*/
        return;
    }
    LRUCache(int capacity) {
        n = capacity;
        L = new Node(-1,-1);
        R = new Node(-1,-1);
        L->right = R;//注意头部和尾部
        R->left = L;
    }
    
    int get(int key) {
        if(hash.count(key) == 0) return -1;
        auto p = hash[key];
        remove(p);//删除当前位置
        insert(p);//放在头部
        return p->value;
    }
    
    void put(int key, int value) {
        if(hash.count(key) == 0)//如果不再当前lru cache中
        {
            if(hash.size() == n)//缓存满了
            {
                auto p = R->left;
                if(p == NULL)
                    return;
                remove(p);
                hash.erase(p->key);
                delete p;
            }
            //没有满,直接插入
            auto p = new Node(key,value);
            hash[key] = p;
            insert(p);
        }
        else //在当前lru缓存中
        {
            auto p = hash[key];
            p->value = value;
            remove(p);
            insert(p);
        }
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值