LeetCode 460 - LFU缓存

题目描述

460. LFU缓存

解法一:哈希表+AVL(C++)

这里的AVL树主要采用C++ STL: :set

时间复杂度: get 时间复杂度 O ( log n ) O(\log n) ,put 时间复杂度 O ( log n ) O(\log n) ,操作的时间复杂度瓶颈在于平衡二叉树的插入删除均需要 O ( log n ) O(\log n) 的时间。

参考 官方题解

struct Node{
    int cnt; // 频度
    int time; // 最近使用时间
    int key, value;
    Node(int _cnt, int _time, int _key, int _value): cnt(_cnt), time(_time), key(_key), value(_value){}
    bool operator < (const Node& rhs) const {
        return cnt == rhs.cnt?(time<rhs.time):(cnt<rhs.cnt);
    }
};

class LFUCache {
    int capacity, time;
    unordered_map<int, Node> key_table;
    set<Node> S;
public:
    LFUCache(int _capacity) {
        capacity = _capacity;
        time = 0;
        key_table.clear();
        S.clear();
    }
    
    int get(int key) {
        if(!capacity) return -1;
        auto it = key_table.find(key);
        if(it==key_table.end()) return -1;
        Node cache = it->second;
        S.erase(cache);
        cache.cnt += 1;
        cache.time = ++time;
        S.insert(cache);
        it->second = cache;
        return cache.value;
    }
    
    void put(int key, int value) {
        if(!capacity) return;
        auto it = key_table.find(key);
        if(it==key_table.end())
        {
            if(key_table.size()==capacity)
            {
                key_table.erase(S.begin()->key);
                S.erase(S.begin());
            }
            Node cache = Node(1, ++time, key, value);
            key_table.insert(make_pair(key, cache));
            S.insert(cache);
        }
        else
        {
            Node cache = it->second;
            S.erase(cache);
            cache.cnt += 1;
            cache.time = ++time;
            cache.value = value;
            S.insert(cache);
            it->second = cache;
        }
    }
};

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache* obj = new LFUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

解法二:双向链表(Python)

在这里插入图片描述
准备两个字典,

  • key与freq映射,为了找key在哪个频率下;
  • key与value映射,为了找key对应的value值,这个需要一个有序字典OrderedDict,为了好弹出同一个频率下,最开始加入的key(当然是容量不够,需要弹出的时候)

对于第二个字典,可以使用python自带库,也可以使用双向链表实现

class Node:
    def __init__(self, key, val):
        self.key = key
        self.val = val
        self.freq = 1
        self.prev = self.next = None
 
class DCLinkedList:
    def __init__(self):
         self.dummy = Node(None, None)
         self.dummy.next = self.dummy
         self.dummy.prev = self.dummy
         self.size = 0
    def append(self, node):
        # 尾插入
        node.prev = self.dummy.prev
        node.next = self.dummy 
        node.prev.next = node
        self.dummy.prev = node
        self.size += 1
    def pop(self, node=None):
        # 头删除
        if self.size == 0: return 
        if node is None:
            node = self.dummy.next
        node.prev.next = node.next
        node.next.prev = node.prev
        self.size -= 1
        return node
    
class LFUCache:
    def __init__(self, capacity: int):
        from collections import defaultdict
        self.key_to_node = {}
        self.freq = defaultdict(DCLinkedList)
        self.min_freq = 0
        self.capacity = capacity

    def get(self, key: int) -> int:
        if key not in self.key_to_node: return -1
        node = self.key_to_node[key]
        node_freq = node.freq
        self.freq[node_freq].pop(node)
        if self.min_freq == node_freq and self.freq[node_freq].size == 0:
            self.min_freq += 1
        node.freq += 1
        self.freq[node.freq].append(node)
        return node.val

    def put(self, key: int, value: int) -> None:
        if not self.capacity: return
        if key in self.key_to_node:
            node = self.key_to_node[key]
            node_freq = node.freq
            self.freq[node_freq].pop(node)
            if self.min_freq == node_freq and self.freq[node_freq].size == 0:
                self.min_freq += 1
            node.freq += 1
            node.val = value
            self.freq[node.freq].append(node)
        else:
            if len(self.key_to_node) == self.capacity:
                node = self.freq[self.min_freq].pop()
                self.key_to_node.pop(node.key)
            node = Node(key, value)
            self.key_to_node[key] = node
            self.freq[1].append(node)
            self.min_freq = 1
            
# Your LFUCache object will be instantiated and called as such:
# obj = LFUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
发布了176 篇原创文章 · 获赞 32 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_38204302/article/details/105345257