LeetCode:LRU and LFU

文章目录

  • [1. LRU](#1. LRU)
  • [2. LFU](#2. LFU)

1. LRU

Leetcode链接

LRU,即least recently used, 即一个具有固定容量的数据结构,其数据淘汰更新策略,根据最近访问,最久未被访问的元素优先被淘汰。

数据结构设计思路:

  • 链表。通过链表的尾部删除,头部插入,可以非常完美地模拟淘汰更新策略。
  • 哈希表。LRU访问,一般是KV结构,要能够通过key,找到value 。 实际中,哈希表建立的是key 到相应元素在链表中迭代器的映射关系 ,这样不仅可以拿到value,同时可以利用迭代器改变链表元素位置。
  • 整型变量。存储容量。
  • pair类型。存储KV键值对
cpp 复制代码
class LRUCache {
public:
    LRUCache(int capacity) {
        capacity_ = capacity;
    }
    int get(int key) {
        if(hash_.count(key) == 0)
            return -1;
        auto it = hash_[key];
        int val = it->second;
        l_.erase(it);
        l_.push_front({key,val});
        hash_[key] = l_.begin();
        return val;
    } 
    
    void put(int key, int value) {
        if(hash_.count(key)) {
            hash_[key]->second = value;
            (void)get(key);
            return;
        }
        if(capacity_ == 0) {
            int key = l_.back().first;
            l_.pop_back();
            hash_.erase(key);
            capacity_++;
        }
        
        l_.push_front({key,value});
        hash_[key] = l_.begin();
        capacity_--;
    }
    
private:
    using pii = pair<int,int>;
    int capacity_;
    list<pii> l_;
    unordered_map<int,list<pii>::iterator> hash_;
};

2. LFU

Leetcode链接

LFU,即 least frequently used, 即最少频次被使用,同样是有一定淘汰更新策略的固定容量的数据结构。

LFU的淘汰更新策略:

  • 超出容量时,优先淘汰被使用频次最低的元素。
  • 相同频次的元素,优先淘汰最久未被使用的元素。

实际上,如果只看一个频次,那么LFU就是LRU,多个LRU分别对应不同频次,就构成了LFU

所以,我们如下设计LFU数据结构:

  • 哈希表。这个哈希表建立的是频次到具体LRU链表的映射,这样可以通过频次,找到存储相应访问频次元素的链表。
  • 哈希表。该哈希表建立的是key到相应元素链表迭代器的映射,这样可以快速定位元素,而无需找到相应链表后,再遍历。
  • 整型变量。存储容量。
  • 整型变量。存储当前最小频次,这样淘汰时,可以快速通过哈希找到相应链表。
  • 元素数据结构。LRU 中,元素数据结构,简单的pair<int,int> 即可,而LFU 中,还需在 keyvalue 外添加频次,因为这样通过哈希拿到相应元素迭代器后,才能知道这个元素在哪个频次的链表中,进而才能进行更改元素位置的操作。
cpp 复制代码
class LFUCache {
public:
    LFUCache(int capacity) {
        capacity_ = capacity;        
        min_fre_ = 0;
    }
    int get(int key) {
        if(hash_.count(key) == 0)
            return -1;        
        int val = hash_[key]->val_;
        int fre = hash_[key]->fre_;

        list<Node>& l = lists_[fre];
        l.erase(hash_[key]);
        if(l.empty()) {
            lists_.erase(fre);
            if(min_fre_ == fre)
                min_fre_++;
        } 
        lists_[fre + 1].push_front(Node(key,val,fre + 1));
        hash_[key] = lists_[fre + 1].begin();
        return val;
    }
    
    void put(int key, int value) {
        if(hash_.count(key)) {
            hash_[key]->val_ = value;
            (void)get(key);
            return;
        }       
        
        if(capacity_ == 0) {
            list<Node>& l = lists_[min_fre_];
            int key = l.back().key_;
            hash_.erase(key);
            l.pop_back();
            if(l.empty())
                lists_.erase(min_fre_);
            capacity_++;
        }

        lists_[1].push_front(Node(key,value,1));
        min_fre_ = 1;
        hash_[key] = lists_[1].begin();
        capacity_--;
    }    
private:
    struct Node {
        int key_;
        int val_;
        int fre_;

        Node(int key,int val,int fre) {
            key_ = key;
            val_ = val;
            fre_ = fre;
        }
    };
    int capacity_;
    int min_fre_;
    unordered_map<int,list<Node>> lists_;
    unordered_map<int,list<Node>::iterator> hash_;
};
相关推荐
发疯幼稚鬼2 小时前
简单介绍各类算法
算法
星诺算法备案2 小时前
算法备案中“落实算法安全主体责任”的实操构建
人工智能·算法·算法备案
你撅嘴真丑2 小时前
完数的判断 , 有规律的数列求和
算法
朔北之忘 Clancy2 小时前
第二章 分支结构程序设计(1)
c++·算法·青少年编程·竞赛·教材·考级·讲义
yongui478342 小时前
异步电机最小二乘法参数辨识的MATLAB实现
算法·matlab·最小二乘法
君义_noip2 小时前
信息学奥赛一本通 1528:【例 2】单词游戏
c++·算法·信息学奥赛·一本通·csp-s
AlenTech3 小时前
238. 除了自身以外数组的乘积 - 力扣(LeetCode)
算法·leetcode·职场和发展
l1t3 小时前
利用豆包辅助编写数独隐式唯一数填充c程序
c语言·开发语言·人工智能·算法·豆包·deepseek
cici158743 小时前
matlab实现NSGA-II(带精英策略的非支配排序遗传算法)
算法