432 All Oone Data Structure
432 All Oone Data Structure
All O`one Data Structure 
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:
1
2
3
4
5
AllOne() Initializes the object of the data structure.
inc(String key) Increments the count of the string key by 1. If key does not exist in the data structure, insert it with count 1.
dec(String key) Decrements the count of the string key by 1. If the count of key is 0 after the decrement, remove it from the data structure. It is guaranteed that key exists 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 "".
Note that each function must run in O(1) average time complexity.
Example 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
**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"
Constraints:
1
2
3
4
1 <= key.length <= 10
key consists of lowercase English letters.
It is guaranteed that for each call to dec, key is existing in the data structure.
At most 5 * 104 calls will be made to inc, dec, getMaxKey, and getMinKey.
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
class Node:
def __init__(self, count=0):
self.next = None
self.prev = None
self.elem = set()
self.count = count
class DLL:
def __init__(self):
self.head = Node() # Sentinel head with count 0
self.tail = Node() # Sentinel tail with count infinity
self.head.next = self.tail
self.tail.prev = self.head
def insert_after(self, node, new_node):
"""Insert new_node after the given node"""
new_node.prev = node
new_node.next = node.next
node.next.prev = new_node
node.next = new_node
def remove(self, node):
"""Remove the node from the list"""
node.prev.next = node.next
node.next.prev = node.prev
def is_empty(self, node):
"""Check if the node has no elements"""
return len(node.elem) == 0
class AllOne:
def __init__(self):
self.hash = {} # Key to node mapping
self.dll = DLL() # Doubly linked list to track counts
def inc(self, key: str) -> None:
if key in self.hash:
node = self.hash[key]
node.elem.remove(key)
# Move to the next node (count + 1)
if node.next.count == node.count + 1:
node.next.elem.add(key)
self.hash[key] = node.next
else:
# Create a new node with count + 1
new_node = Node(node.count + 1)
new_node.elem.add(key)
self.dll.insert_after(node, new_node)
self.hash[key] = new_node
# Remove the node if it's empty
if self.dll.is_empty(node):
self.dll.remove(node)
else:
# Insert the key with count 1 in the node after head
if self.dll.head.next.count == 1:
self.dll.head.next.elem.add(key)
self.hash[key] = self.dll.head.next
else:
new_node = Node(1)
new_node.elem.add(key)
self.dll.insert_after(self.dll.head, new_node)
self.hash[key] = new_node
def dec(self, key: str) -> None:
if key not in self.hash:
return
node = self.hash[key]
node.elem.remove(key)
if node.count > 1:
# Move to the previous node (count - 1)
if node.prev.count == node.count - 1:
node.prev.elem.add(key)
self.hash[key] = node.prev
else:
# Create a new node with count - 1
new_node = Node(node.count - 1)
new_node.elem.add(key)
self.dll.insert_after(node.prev, new_node)
self.hash[key] = new_node
else:
# If count becomes 0, remove the key from hash
del self.hash[key]
# Remove the node if it's empty
if self.dll.is_empty(node):
self.dll.remove(node)
def getMaxKey(self) -> str:
if self.dll.tail.prev == self.dll.head:
return ""
return next(iter(self.dll.tail.prev.elem))
def getMinKey(self) -> str:
if self.dll.head.next == self.dll.tail:
return ""
return next(iter(self.dll.head.next.elem))
This post is licensed under CC BY 4.0 by the author.