题目浅析

  • 想查看原题可以点击题目链接

  • 简单地说,就是给一个数组和一个窗口大小 k,现在规定这个窗口从数组最左侧移到最右侧,求每个窗口的中位数。

思路分享

代码解答(强烈建议自行解答后再看)

  • 参考题解
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
class LazyHeap:
def __init__(self):
self.heap = []
self.size = 0
self.remove_cnt = defaultdict(int)

def push(self, num):
self.apply_remove()
heappush(self.heap, num)
self.size += 1

def pop(self) -> int:
self.size -= 1
return heappop(self.heap)

def pushpop(self, num) -> int:
self.apply_remove()
return heappushpop(self.heap, num)

def top(self) -> int:
self.apply_remove()
return self.heap[0]

def remove(self, num):
self.remove_cnt[num] += 1
self.size -= 1

def apply_remove(self):
while self.heap and self.remove_cnt[self.heap[0]]:
self.remove_cnt[self.heap[0]] -= 1
heappop(self.heap)



class Solution:
def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
left = LazyHeap()
right = LazyHeap()

n = len(nums)
ans = [0] * (n-k+1)
for i, x in enumerate(nums):
if left.size <= right.size:
left.push(-right.pushpop(x))
else:
right.push(-left.pushpop(-x))

if i < k-1:
continue

if k % 2 == 0:
ans[i-k+1] = (-left.top() + right.top()) / 2
else:
ans[i-k+1] = -left.top()

to_remove = nums[i-k+1]
if to_remove > -left.top():
right.remove(to_remove)
if left.size > right.size + 1:
right.push(-left.pop())
else:
left.remove(-to_remove)
if left.size < right.size:
left.push(-right.pop())
return ans