Skip to content

Commit 2bd1f4a

Browse files
committed
Sync LeetCode submission Runtime - 67 ms (62.89%), Memory - 34.5 MB (47.27%)
1 parent 2707525 commit 2bd1f4a

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<p>Design a data structure to store the strings&#39; count with the ability to return the strings with minimum and maximum counts.</p>
2+
3+
<p>Implement the <code>AllOne</code> class:</p>
4+
5+
<ul>
6+
<li><code>AllOne()</code> Initializes the object of the data structure.</li>
7+
<li><code>inc(String key)</code> Increments the count of the string <code>key</code> by <code>1</code>. If <code>key</code> does not exist in the data structure, insert it with count <code>1</code>.</li>
8+
<li><code>dec(String key)</code> Decrements the count of the string <code>key</code> by <code>1</code>. If the count of <code>key</code> is <code>0</code> after the decrement, remove it from the data structure. It is guaranteed that <code>key</code> exists in the data structure before the decrement.</li>
9+
<li><code>getMaxKey()</code> Returns one of the keys with the maximal count. If no element exists, return an empty string <code>&quot;&quot;</code>.</li>
10+
<li><code>getMinKey()</code> Returns one of the keys with the minimum count. If no element exists, return an empty string <code>&quot;&quot;</code>.</li>
11+
</ul>
12+
13+
<p><strong>Note</strong> that each function must run in <code>O(1)</code> average time complexity.</p>
14+
15+
<p>&nbsp;</p>
16+
<p><strong class="example">Example 1:</strong></p>
17+
18+
<pre>
19+
<strong>Input</strong>
20+
[&quot;AllOne&quot;, &quot;inc&quot;, &quot;inc&quot;, &quot;getMaxKey&quot;, &quot;getMinKey&quot;, &quot;inc&quot;, &quot;getMaxKey&quot;, &quot;getMinKey&quot;]
21+
[[], [&quot;hello&quot;], [&quot;hello&quot;], [], [], [&quot;leet&quot;], [], []]
22+
<strong>Output</strong>
23+
[null, null, null, &quot;hello&quot;, &quot;hello&quot;, null, &quot;hello&quot;, &quot;leet&quot;]
24+
25+
<strong>Explanation</strong>
26+
AllOne allOne = new AllOne();
27+
allOne.inc(&quot;hello&quot;);
28+
allOne.inc(&quot;hello&quot;);
29+
allOne.getMaxKey(); // return &quot;hello&quot;
30+
allOne.getMinKey(); // return &quot;hello&quot;
31+
allOne.inc(&quot;leet&quot;);
32+
allOne.getMaxKey(); // return &quot;hello&quot;
33+
allOne.getMinKey(); // return &quot;leet&quot;
34+
</pre>
35+
36+
<p>&nbsp;</p>
37+
<p><strong>Constraints:</strong></p>
38+
39+
<ul>
40+
<li><code>1 &lt;= key.length &lt;= 10</code></li>
41+
<li><code>key</code> consists of lowercase English letters.</li>
42+
<li>It is guaranteed that for each call to <code>dec</code>, <code>key</code> is existing in the data structure.</li>
43+
<li>At most <code>5 * 10<sup>4</sup></code>&nbsp;calls will be made to <code>inc</code>, <code>dec</code>, <code>getMaxKey</code>, and <code>getMinKey</code>.</li>
44+
</ul>
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Approach: Using Doubly Linked List
2+
3+
# Time: O(1)
4+
# Space: O(n)
5+
6+
class Node:
7+
def __init__(self, freq):
8+
self.freq = freq
9+
self.prev = None
10+
self.next = None
11+
self.keys = set()
12+
13+
class AllOne:
14+
15+
def __init__(self):
16+
self.head = Node(0) # Dummy head
17+
self.tail = Node (0) # Dummy tail
18+
self.head.next = self.tail
19+
self.tail.prev = self.head
20+
self.map = {} # Mapping from key to its node
21+
22+
23+
def inc(self, key: str) -> None:
24+
if key in self.map:
25+
node = self.map[key]
26+
freq = node.freq
27+
node.keys.remove(key) # Remove key from current node
28+
29+
next_node = node.next
30+
if next_node == self.tail or next_node.freq != freq + 1:
31+
# Create new node
32+
new_node = Node(freq + 1)
33+
new_node.keys.add(key)
34+
new_node.prev = node
35+
new_node.next = next_node
36+
node.next = new_node
37+
next_node.prev = new_node
38+
self.map[key] = new_node
39+
40+
else:
41+
# Add key in the next node
42+
next_node.keys.add(key)
43+
self.map[key] = next_node
44+
45+
# Remove the current node if it has no keys left
46+
if not node.keys:
47+
self._removeNode(node)
48+
49+
# Key does not exist
50+
else:
51+
first_node = self.head.next
52+
if first_node == self.tail or first_node.freq > 1:
53+
# Create new node
54+
new_node = Node(1)
55+
new_node.keys.add(key)
56+
new_node.prev = self.head
57+
new_node.next = first_node
58+
self.head.next = new_node
59+
first_node.prev = new_node
60+
self.map[key] = new_node
61+
else: # Freq is 1
62+
first_node.keys.add(key)
63+
self.map[key] = first_node
64+
65+
66+
def dec(self, key: str) -> None:
67+
if key not in self.map:
68+
return # Key does not exist
69+
70+
node = self.map[key]
71+
node.keys.remove(key)
72+
freq = node.freq
73+
74+
if freq == 1:
75+
# Remove the key from the map if freq is 1
76+
del self.map[key]
77+
else:
78+
prev_node = node.prev
79+
if prev_node == self.head or prev_node.freq != freq - 1:
80+
# Creae a new node
81+
new_node = Node(freq - 1)
82+
new_node.keys.add(key)
83+
new_node.prev = prev_node
84+
new_node.next = node
85+
prev_node.next = new_node
86+
node.prev = new_node
87+
self.map[key] = new_node
88+
else:
89+
# Decrement the existing previous node
90+
prev_node.keys.add(key)
91+
self.map[key] = prev_node
92+
93+
# Remove node if it has no keys left
94+
if not node.keys:
95+
self._removeNode(node)
96+
97+
98+
def getMaxKey(self) -> str:
99+
if self.tail.prev == self.head:
100+
return '' # No keys exist
101+
return next(iter(self.tail.prev.keys)) # Return one of the keys from tail's prev node
102+
103+
104+
def getMinKey(self) -> str:
105+
if self.head.next == self.tail:
106+
return '' # No keys exist
107+
return next(iter(self.head.next.keys)) # Return one of the keys from head's next node
108+
109+
110+
def _removeNode(self, node):
111+
prev_node = node.prev
112+
next_node = node.next
113+
114+
prev_node.next = next_node
115+
next_node.prev = prev_node
116+
117+
118+
119+
120+
# Your AllOne object will be instantiated and called as such:
121+
# obj = AllOne()
122+
# obj.inc(key)
123+
# obj.dec(key)
124+
# param_3 = obj.getMaxKey()
125+
# param_4 = obj.getMinKey()

0 commit comments

Comments
 (0)