-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathdesign-an-array-statistics-tracker.py
82 lines (71 loc) · 2.53 KB
/
design-an-array-statistics-tracker.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
# Time: ctor: O(1)
# addNumber: O(logn)
# removeFirstAddedNumber: O(logn)
# getMean: O(1)
# getMedian: O(1)
# getMode: O(1)
# Space: O(n)
# deque, freq table, sorted list
from sortedcontainers import SortedList
import collections
class StatisticsTracker(object):
def __init__(self):
self.__total = 0
self.__dq = collections.deque()
self.__sl1 = SortedList()
self.__sl2 = SortedList()
self.__num_to_freq = collections.defaultdict(int)
self.__sorted_freqs = SortedList()
self.__freq_to_nums = collections.defaultdict(SortedList)
def __update(self, number, d):
if number in self.__num_to_freq:
self.__freq_to_nums[self.__num_to_freq[number]].remove(number)
if not self.__freq_to_nums[self.__num_to_freq[number]]:
del self.__freq_to_nums[self.__num_to_freq[number]]
self.__sorted_freqs.remove(self.__num_to_freq[number])
self.__num_to_freq[number] += d
if not self.__num_to_freq[number]:
del self.__num_to_freq[number]
else:
if not self.__freq_to_nums[self.__num_to_freq[number]]:
self.__sorted_freqs.add(self.__num_to_freq[number])
self.__freq_to_nums[self.__num_to_freq[number]].add(number)
def __rebalance(self):
if len(self.__sl2) == len(self.__sl1)+2:
self.__sl1.add(self.__sl2.pop(0))
elif len(self.__sl2)+1 == len(self.__sl1):
self.__sl2.add(self.__sl1.pop(-1))
def addNumber(self, number):
"""
:type number: int
:rtype: None
"""
self.__total += number
self.__dq.append(number)
self.__update(number, +1)
(self.__sl2 if not self.__sl2 or self.__sl2[0] <= number else self.__sl1).add(number)
self.__rebalance()
def removeFirstAddedNumber(self):
"""
:rtype: None
"""
number = self.__dq.popleft()
self.__total -= number
self.__update(number, -1)
(self.__sl2 if number in self.__sl2 else self.__sl1).remove(number)
self.__rebalance()
def getMean(self):
"""
:rtype: int
"""
return self.__total//len(self.__dq)
def getMedian(self):
"""
:rtype: int
"""
return self.__sl2[0]
def getMode(self):
"""
:rtype: int
"""
return self.__freq_to_nums[self.__sorted_freqs[-1]][0]