LFU Cache

update Aug 24, 2017 23:14

LeetCodearrow-up-right

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. 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

Basic Idea:

这里arrow-up-right 有一个非常不错的分析文章。

在我的实现中,整个数据结构示意图:

基本思想就是:

  • 外层: 维护FreqNode系统,保证O(1)时间找到任何freq的fnode(利用FreqMap),同时要做到产生新的freq时候要增加fnode,内部 dnode 为空时候要删除 fnode;

  • 内层: 在每个 fnode 下面维护 DataNode 的链表。当某 dnode 的 freq 提升时(该key被set或者get),要将其移动到 freq+1 的 fnode 下。同时在每个 fnode 内部的链表中保持 LRU 原则,即从tail插入,从head删除;

  • 另外,当cache满,需要删除现有dnode时候,选择最左边 fnode 下的 dnode 进行删除。

Java Code:

Python Code

Last updated