Date and Time: Jun 18, 2026, 12:00 (EST)
Link: https://leetcode.com/problems/all-oone-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:
-
AllOne()Initializes the object of the data structure. -
void inc(String key)Increments the count of the stringkeyby1. Ifkeydoes not exist in the data structure, insert it with count1. -
void 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. -
String getMaxKey()Returns one of the keys with the maximal count. If no element exists, return an empty string"". -
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:
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"
-
1 <= key.length <= 10 -
keyconsists of lowercase English letters. -
It is guaranteed that for each call to
dec,keyis existing in the data structure. -
At most
5 * 10^4calls will be made toinc,dec,getMaxKey, andgetMinKey.
Use a doubly linked list where each node holds a frequency and a set of all keys at that frequency. Two dummy nodes left and right serve as sentinels (left = min end, right = max end). A hashmap {key: node} tracks which node each key lives in.
insert(node, newNode) — inserts newNode immediately after node.
delete(node) — unlinks node from the list and clears its pointers.
inc(key):
- If key exists in
hashmap, look atnode.next. If it doesn't exist or has the wrong frequency (node.frequency + 1), create a new node there. - Add key to
node.next.val, updatehashmap[key], remove key from old node, delete old node if empty. - If key doesn't exist, check if
left.nexthasfrequency == 1; if not, create a new node. Add key there.
dec(key):
- If
frequency > 1, look atnode.prev. If it doesn't exist or has the wrong frequency (node.frequency - 1), create a new node there. - Move key to
node.prev, remove from old node, delete old node if empty. - If
frequency == 1, remove key from the node and fromhashmap; delete node if empty.
getMaxKey() — return any key from right.prev.val.
getMinKey() — return any key from left.next.val.
class Node:
def __init__(self):
self.prev, self.next = None, None
self.frequency, self.keyStore = 0, set()
class AllOne:
# Save string with their counts
# Linked list to hold all strings with their counts
# Min key on the left, max key on the right
# Each node holds one count, all the strings with the same cnt will be saved in the same node
# SC: O(n)
def __init__(self):
self.hashmap = {} # {key: node}
self.left, self.right = Node(), Node()
self.left.next, self.right.prev = self.right, self.left
def insert(self, node, newNode):
left, right = node, node.next
left.next, right.prev = newNode, newNode
newNode.prev, newNode.next = left, right
def delete(self, node):
left, right = node.prev, node.next
left.next, right.prev = right, left
# 1. Check if key exists
# 2. Promote: move key from current node to next node, remember to check if next node exists
def inc(self, key: str) -> None:
if key in self.hashmap:
node = self.hashmap[key]
# Check if next frequency+1 node exists
if node.next.frequency == node.frequency+1:
# Add into next frequency node and remove from current node
node.next.keyStore.add(key)
self.hashmap[key] = node.next
# Remove from current node
node.keyStore.remove(key)
if len(node.keyStore) == 0:
self.delete(node)
# Else, we create new node
else:
newNode = Node()
newNode.frequency = node.frequency + 1
newNode.keyStore.add(key)
# Insert new node into linked list
self.insert(node, newNode)
self.hashmap[key] = newNode
# Remove key from old node
node.keyStore.remove(key)
if len(node.keyStore) == 0:
self.delete(node)
# Initialize key to frequency = 1 node
else:
# Check if frequency = 1 node exists
if self.left.next.frequency == 1:
self.left.next.keyStore.add(key)
self.hashmap[key] = self.left.next
else:
newNode = Node()
newNode.frequency = 1
newNode.keyStore.add(key)
self.insert(self.left, newNode)
self.hashmap[key] = newNode
# 1. Move down the key to the prev node
# 2. Remember to check if frequency-1 node exists
def dec(self, key: str) -> None:
node = self.hashmap[key]
# Check if key in frequency = 1 node
if node.frequency == 1:
node.keyStore.remove(key)
del self.hashmap[key]
if not node.keyStore:
self.delete(node)
else:
# Move it to frequency - 1 node
if node.prev.frequency == node.frequency-1:
newNode = node.prev
newNode.keyStore.add(key)
self.hashmap[key] = newNode
# Need to create frequency - 1 node
else:
newNode = Node()
newNode.frequency = node.frequency - 1
newNode.keyStore.add(key)
self.hashmap[key] = newNode
self.insert(node.prev, newNode)
# Remove from oldNode
node.keyStore.remove(key)
# Check if oldNode needs to be deleted
if len(node.keyStore) == 0:
self.delete(node)
# Get right node.prev
def getMaxKey(self) -> str:
if self.right.prev == self.left:
return ""
else:
for val in self.right.prev.keyStore:
return val
# Get left node.next
def getMinKey(self) -> str:
if self.left.next == self.right:
return ""
else:
for val in self.left.next.keyStore:
return val
# Your AllOne object will be instantiated and called as such:
# obj = AllOne()
# obj.inc(key)
# obj.dec(key)
# param_3 = obj.getMaxKey()
# param_4 = obj.getMinKey()Time Complexity:
Space Complexity: n is the total number of unique keys.