-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy path432.all-oone-data-structure.py
140 lines (121 loc) · 4.46 KB
/
432.all-oone-data-structure.py
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# Tag: Hash Table, Linked List, Design, Doubly-Linked List
# Time: O(1)
# Space: O(N)
# Ref: -
# Note: -
# 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 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:
#
# 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 <= 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.
#
#
class ListNode:
def __init__(self, count, key):
self.count = count
self.keys = set([key])
self.pre = None
self.next = None
class AllOne:
def __init__(self):
self.key_count = {}
self.count_node = {}
self.head = ListNode(0, None)
self.tail = ListNode(0, None)
self.head.next = self.tail
self.tail.pre = self.head
def insert_after(self, pre, cur):
cur.next = pre.next
cur.next.pre = cur
cur.pre = pre
pre.next = cur
def remove(self, cur):
cur.pre.next = cur.next
cur.next.pre = cur.pre
del self.count_node[cur.count]
def inc(self, key: str) -> None:
count = self.key_count.get(key, 0) + 1
self.key_count[key] = count
if count == 1:
if 1 not in self.count_node:
new_node = ListNode(1, key)
self.count_node[1] = new_node
self.insert_after(self.head, new_node)
else:
self.count_node[1].keys.add(key)
else:
cur = self.count_node[count - 1]
cur.keys.remove(key)
pre = cur
if len(cur.keys) == 0:
pre = cur.pre
self.remove(cur)
if count not in self.count_node:
new_node = ListNode(count, key)
self.count_node[count] = new_node
self.insert_after(pre, new_node)
else:
self.count_node[count].keys.add(key)
def dec(self, key: str) -> None:
if key not in self.key_count:
return
count = self.key_count[key]
if count == 1:
del self.key_count[key]
cur = self.count_node[1]
cur.keys.remove(key)
if len(cur.keys) == 0:
self.remove(cur)
else:
self.key_count[key] = count - 1
cur = self.count_node[count]
cur.keys.remove(key)
if len(cur.keys) == 0:
self.remove(cur)
if count - 1 not in self.count_node:
node = ListNode(count - 1, key)
self.insert_after(cur.pre, node)
self.count_node[count - 1] = node
else:
self.count_node[count - 1].keys.add(key)
def getMaxKey(self) -> str:
return "" if self.tail.pre == self.head else next(iter(self.tail.pre.keys))
def getMinKey(self) -> str:
return "" if self.head.next == self.tail else next(iter(self.head.next.keys))
# 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()