<div>
Design a data structure to store the strings' count with the ability to return the strings with minimum and maximum counts.
Implement the AllOne class:
AllOne()Initializes the object of the data structure.inc(String key)Increments the count of the stringkeyby1. Ifkeydoes not exist in the data structure, insert it with count1.dec(String key)Decrements the count of the stringkeyby1. If the count ofkeyis0after the decrement, remove it from the data structure. It is guaranteed thatkeyexists in the data structure before the decrement.getMaxKey()Returns one of the keys with the maximal count. If no element exists, return an empty string"".getMinKey()Returns one of the keys with the minimum count. If no element exists, return an empty string"".
Example 1:
<pre>Input ["AllOne", "inc", "inc", "getMaxKey", "getMinKey", "inc", "getMaxKey", "getMinKey"] [[], ["hello"], ["hello"], [], [], ["leet"], [], []] Output [null, null, null, "hello", "hello", null, "hello", "leet"]
Explanation AllOne allOne = new AllOne(); allOne.inc("hello"); allOne.inc("hello"); allOne.getMaxKey(); // return "hello" allOne.getMinKey(); // return "hello" allOne.inc("leet"); allOne.getMaxKey(); // return "hello" allOne.getMinKey(); // return "leet" </pre>
Constraints:
1 <= key.length <= 10keyconsists of lowercase English letters.- It is guaranteed that for each call to
dec,keyis existing in the data structure. - At most
5 * 10<sup>4</sup>calls will be made toinc,dec,getMaxKey, andgetMinKey.
</div>
题目大意:
设计数据结构,使其支持增加或减少一个单词的频数,最大或最小单词的频数。注意最小频数不能为0
解题思路:
这个频数有点似LRU的分层思路,加入self.max_freq, 其他操作都可以实现,但是dec操作不能达到O(1), 因为若某个最小频数单词从1变成0,需要检索频率到下一个有节点的层。
改进就是要将频率的的值连起来,所以参考LRU,map的key是频率,value是node,node中含有freq,形成一个环。而node含有该频率对应的单词set,inc/dec就是将单词移动另一个node中
解题步骤:
N/A
注意事项:
- 与LRU区别: map的key是频率,node含有频率和单词set,数据结构加入key_to_count。LL是从最大频率到最小频率
- inc操作将节点从原频率node移到下一个频率node,若新node不存在,调用append_before. 然后从原频率node的单词set中删除该单词,若set为空,删除此node以及map中的entry
- dec与inc类似,但要注意频率变成0的情况:不移到新的node,且从key_to_count中删除该单词
Python代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80class AllOne(TestCases):
def __init__(self):
self.freq_to_node = {}
self.head = ListNode(0)
self.tail = ListNode(0)
self.head.next, self.tail.prev = self.tail, self.head
self.key_to_count = collections.defaultdict(int)
def inc(self, key: str) -> None:
count = self.key_to_count[key]
old_node = self.freq_to_node[count] if count in self.freq_to_node else self.tail
count += 1
if count not in self.freq_to_node:
self.freq_to_node[count] = self.append_before(old_node)
new_node = self.freq_to_node[count]
new_node.key_set.add(key)
self.key_to_count[key] = count
count -= 1
if count in self.freq_to_node and key in self.freq_to_node[count].key_set:
self.freq_to_node[count].key_set.remove(key)
if len(self.freq_to_node[count].key_set) == 0:
self.remove_node(self.freq_to_node[count])
self.freq_to_node.pop(count) # remember
def dec(self, key: str) -> None:
count = self.key_to_count[key]
old_node = self.freq_to_node[count] if count in self.freq_to_node else self.head
count -= 1
if count > 0: # remember
if count not in self.freq_to_node:
self.freq_to_node[count] = self.append_after(old_node)
new_node = self.freq_to_node[count]
new_node.key_set.add(key)
self.key_to_count[key] = count
else:
self.key_to_count.pop(key)
count += 1
if count in self.freq_to_node and key in self.freq_to_node[count].key_set:
self.freq_to_node[count].key_set.remove(key)
if len(self.freq_to_node[count].key_set) == 0:
self.remove_node(self.freq_to_node[count])
self.freq_to_node.pop(count)
def getMaxKey(self) -> str:
node = self.head.next
return '' if node == self.tail else next(iter(node.key_set))
def getMinKey(self) -> str:
node = self.tail.prev
return '' if node == self.head else next(iter(node.key_set))
def append_before(self, node):
new_node = ListNode(node.freq + 1)
predecessor, successor = node.prev, node
predecessor.next, new_node.prev = new_node, predecessor
new_node.next, successor.prev = successor, new_node
return new_node
def append_after(self, node):
new_node = ListNode(node.freq - 1)
predecessor, successor = node, node.next
predecessor.next, new_node.prev = new_node, predecessor
new_node.next, successor.prev = successor, new_node
return new_node
def remove_node(self, node):
predecessor, successor = node.prev, node.next
predecessor.next, successor.prev = successor, predecessor
node.prev, node.next = None, None
class ListNode:
def __init__(self, freq=0, next=None, prev=None):
self.key_set = set()
self.freq = freq
self.next = next
self.prev = prev
算法分析:
时间复杂度为O(1),空间复杂度O(n)


