460. LFU Cache

460. LFU Cache

  • Total Accepted: 5305
  • Total Submissions: 26292
  • Difficulty: Hard
  • Contributors: 1337c0d3rfishercoder

Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: getand put.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., two or more keys that have the same frequency), the least recently used key would be evicted.

Follow up:
Could you do both operations in O(1) time complexity?

Example:

LFUCache cache = new LFUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.get(3);       // returns 3.
cache.put(4, 4);    // evicts key 1.
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4

题目大意:

为“最不常使用缓存”(LFU cache)设计实现数据结构。应当支持get和set操作。

get(key) - 如果存在key,返回其对应的value,否则返回-1。

set(key, value) - 如果不存在key,新增value;否则替换原始value。当缓存容量满时,应当将最不常使用的项目移除。如果存在使用频度相同的多个项目,则移除最近最少使用(Least Recently Used)的项目。

进一步思考:

能否在O(1)时间完成操作?

解题思路:

双向链表(Doubly Linked List) + 哈希表(Hash Table)

首先定义双向链表节点:KeyNode(Key节点)与FreqNode(频度节点)。

KeyNode中保存key(键),value(值),freq(频度),prev(前驱),next(后继)

FreqNode中保存freq(频度)、prev(前驱)、next(后继)、first(指向最新的KeyNode),last(指向最老的KeyNode)

在数据结构LFUCache中维护如下属性:

capacity:缓存的容量

keyDict:从key到KeyNode的映射

freqDict:从freq到FreqNode的映射

head:指向最小的FreqNode

整体数据结构设计如下图所示:

head --- FreqNode1 ---- FreqNode2 ---- ... ---- FreqNodeN
              |               |                       |
            first           first                   first
              |               |                       |
           KeyNodeA        KeyNodeE                KeyNodeG
              |               |                       |
           KeyNodeB        KeyNodeF                KeyNodeH
              |               |                       |
           KeyNodeC         last                   KeyNodeI
              |                                       |
           KeyNodeD                                 last
              |
            last

LFUCache操作实现如下:

set(key, value):

如果capacity为0,忽略当前操作,结束

如果keyDict中包含key,则替换其value,更新节点频度,结束

否则,如果当前keyDict的长度 == capcity,移除head.last(频度最低且最老的KeyNode)

新增KeyNode(key, value),加入keyDict,并更新freqDict

get(key):

若keyDict中包含key,则更新节点频度,返回对应的value

否则,返回-1

节点频度的更新:

从keyDict中找到对应的KeyNode,然后通过KeyNode的freq值,从freqDict找到对应的FreqNode

如果FreqNode的next节点不等于freq + 1,则在其右侧插入一个值为freq + 1的新FreqNode节点

将KeyNode的freq值+1后,从当前KeyNode链表转移到新的FreqNode对应的KeyNode链表

如果KeyNode移动之后,原来的FreqNode对应的KeyNode链表为空,则删除原来的FreqNode

在操作完毕后如果涉及到head的变更,则更新head
时间: 2024-12-13 09:42:30

460. LFU Cache的相关文章

[LeetCode] 460. LFU Cache 最近最不常用页面置换缓存器

Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: get and put. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.pu

LeetCode "460. LFU Cache" !

My first try was very close to a final solution .. however, this is a much neater solution: https://discuss.leetcode.com/topic/69436/concise-c-o-1-solution-using-3-hash-maps-with-explanation Lesson learnt: data structure is crucial. And, if some logi

[LeetCode] LFU Cache 最近最不常用页面置换缓存器

Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: get and put. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.pu

Leetcode: LFU Cache && Summary of various Sets: HashSet, TreeSet, LinkedHashSet

Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. s

Lintcode24 LFU Cache solution 题解

[题目描述] LFU (Least Frequently Used) is a famous cache eviction algorithm.For a cache with capacity k, if the cache is full and need to evict a key in it, the key with the lease frequently used will be kicked out.Implement set and get method for LFU ca

460. LFU缓存

题目地址:https://leetcode-cn.com/problems/lfu-cache/submissions/ 代码地址:https://github.com/javartisan/edx-ds/blob/master/src/main/java/com/javartisan/leetcode/LFUCache460.java class LFUCache { private static class Node{ public int key=-1; public int value=

lfu cache

void splice (iterator position, list& x, iterator i);  //将列表x中迭代器 i 指向的元素移到当前list的position指向的位置处,由于i指向的元素从列表x中被移除,所以迭代器 i 此时是invalid的:position是当前列表的迭代器,i是列表x的迭代器 class LRUCache{ public: LRUCache(int capacity) { cap = capacity; } int get(int key) { au

leetcode 460 LFU缓存

原题点这里 class Node implements Comparable<Node>{ public int key; public int value; public int lastTime; public int fre; public Node(int key,int value,int lastTime){ this.key=key; this.value=value; this.lastTime = lastTime; this.fre=1; } @Override publi

继续过Hard题目.0209

http://www.cnblogs.com/charlesblc/p/6372971.html 继续过Hard模式的题目吧.   # Title Editorial Acceptance Difficulty Frequency   . 65 Valid Number     12.6% Hard    . 126 Word Ladder II     13.6% Hard    . 149 Max Points on a Line     15.6% Hard    . 146 LRU Ca