-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSlidingWindowMedian.py
75 lines (57 loc) · 1.89 KB
/
SlidingWindowMedian.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
import collections
import heapq
from typing import List
class MedianFinder:
def __init__(self):
self.small, self.large = [], []
self.lazy = collections.defaultdict(int)
self.balance = 0
def add(self, num):
if not self.small or num <= -self.small[0]:
heapq.heappush(self.small, -num)
self.balance -= 1
else:
heapq.heappush(self.large, num)
self.balance += 1
self.rebalance()
def remove(self, num):
self.lazy[num] += 1
if num <= -self.small[0]:
self.balance += 1
else:
self.balance -= 1
self.rebalance()
self.lazy_remove()
def find_median(self):
if self.balance < 0:
return -self.small[0]
elif self.balance > 0:
return self.large[0]
return (-self.small[0] + self.large[0]) / 2.0
def rebalance(self):
if self.balance == -1:
return
while self.balance < 0:
heapq.heappush(self.large, -heapq.heappop(self.small))
self.balance += 2
while self.balance > 0:
heapq.heappush(self.small, -heapq.heappop(self.large))
self.balance -= 2
def lazy_remove(self):
while self.small and self.lazy[-self.small[0]] > 0:
self.lazy[-self.small[0]] -= 1
heapq.heappop(self.small)
while self.large and self.lazy[self.large[0]] > 0:
self.lazy[self.large[0]] -= 1
heapq.heappop(self.large)
# O(n * log(k)) time || O(n) space
def median_sliding_window(self, nums: List[int], k: int) -> List[float]:
res = []
median_finder = MedianFinder()
for i, num in enumerate(nums):
median_finder.add(num)
if i >= k:
median_finder.remove(nums[i - k])
if i >= k - 1:
res.append(median_finder.find_median())
return res