Algorithm
本周选择的算法题是:LFU Cache。
规则
Design and implement a data structure for a Least Frequently Used (LFU) cache.
Implement the LFUCache class:
LFUCache(int capacity)Initializes the object with thecapacityof the data structure.int get(int key)Gets the value of thekeyif thekeyexists in the cache. Otherwise, returns-1.void put(int key, int value)Update the value of thekeyif present, or inserts thekeyif not already present. When the cache reaches itscapacity, it should invalidate and remove the least frequently used key before inserting a new item. For this problem, when there is a tie (i.e., two or more keys with the same frequency), the least recently usedkeywould be invalidated.
To determine the least frequently used key, a use counter is maintained for each key in the cache. The key with the smallest use counter is the least frequently used key.
When a key is first inserted into the cache, its use counter is set to 1 (due to the put operation). The use counter for a key in the cache is incremented either a get or put operation is called on it.
The functions get and put must each run in O(1) average time complexity.
Example 1:
Input
["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, 3, null, -1, 3, 4]
Explanation
// cnt(x) = the use counter for key x
// cache=[] will show the last used order for tiebreakers (leftmost element is most recent)
LFUCache lfu = new LFUCache(2);
lfu.put(1, 1); // cache=[1,_], cnt(1)=1
lfu.put(2, 2); // cache=[2,1], cnt(2)=1, cnt(1)=1
lfu.get(1); // return 1
// cache=[1,2], cnt(2)=1, cnt(1)=2
lfu.put(3, 3); // 2 is the LFU key because cnt(2)=1 is the smallest, invalidate 2.
// cache=[3,1], cnt(3)=1, cnt(1)=2
lfu.get(2); // return -1 (not found)
lfu.get(3); // return 3
// cache=[3,1], cnt(3)=2, cnt(1)=2
lfu.put(4, 4); // Both 1 and 3 have the same cnt, but 1 is LRU, invalidate 1.
// cache=[4,3], cnt(4)=1, cnt(3)=2
lfu.get(1); // return -1 (not found)
lfu.get(3); // return 3
// cache=[3,4], cnt(4)=1, cnt(3)=3
lfu.get(4); // return 4
// cache=[3,4], cnt(4)=2, cnt(3)=3
Constraints:
0 <= capacity <= 1040 <= key <= 1050 <= value <= 109- At most
2 * 105calls will be made togetandput.
Solution
class Node:
"""
双向链表的节点抽象
"""
def __init__(self, key, value):
self.key = key
self.value = value
self.frequency = 1
self.previous = self.next = None
class LinkedList:
"""
双向链表,用于记录同一个频率下的所有节点
"""
def __init__(self):
self.dummy = Node(None, None)
self.dummy.next = self.dummy.previous = self.dummy
self.size = 0
def __len__(self):
return self.size
def push(self, node):
node.next = self.dummy.next
node.previous = self.dummy
node.next.previous = node
self.dummy.next = node
self.size += 1
def pop(self, node = None):
if self.size == 0: return None
if node is None:
node = self.dummy.previous
node.previous.next = node.next
node.next.previous = node.previous
self.size -= 1
return node
class LFUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.size = self.min_frequency = 0
self.nodes = {}
self.linkedLists = defaultdict(LinkedList)
def get(self, key: int) -> int:
if key not in self.nodes: return -1
node = self.nodes.get(key)
self._update(node)
return node.value
def put(self, key: int, value: int) -> None:
if self.capacity == 0: return None
node = self.nodes.get(key)
if node is None:
if self.size == self.capacity:
node = self.linkedLists[self.min_frequency].pop()
del self.nodes[node.key]
self.size -= 1
node = Node(key, value)
self.nodes[key] = node
self.size += 1
self.min_frequency = 1
self.linkedLists[1].push(node)
else:
self._update(node)
node.value = value
def _update(self, node):
linkedList = self.linkedLists[node.frequency]
linkedList.pop(node)
if self.min_frequency == node.frequency and not self.linkedLists[self.min_frequency]:
self.min_frequency += 1
node.frequency += 1
self.linkedLists[node.frequency].push(node)
Review
Django 4.0 release notes - UNDER DEVELOPMENT
按计划,Django 将在 12月6号发布 4.0 的正式版,届时将带来官方的 Redis 支持。Redis 作为当下最流行的内存数据库,广泛的应用在各大领域中,Python 的流行框架 Celery 也建立了基于 Redis 的消息传输、结果存储的中间件。
Tip
一个有趣网站,用 div 画画: A Single Div。
Share
媳妇作为组织者之一策划了一场万圣节活动~ 我带女儿参加,现场看她手忙脚乱,好在还是拿了不少玩具回去,最后我拍照留恋 :)

(ps: 拍照时她不看我…)
