对于一个数组,求解位置 i i i之前的 k k k个(包括当前位置)数中的最大数。
最直接的方法就是针对当前位置往前搜索比较k-1个数,得到最大的那个数。该方法的时间复杂度为 O ( N ∗ K ) O(N*K) O(N∗K)。能否在 O ( N ) O(N) O(N)的时间复杂度中求解呢?
当然是可以的,我们只需要记住历史K中的最大与第二大的数以及这两个数的生命周期,然后通过不停地前移,我们不停更新这个两个数就可。【这便是思路了】
特别的,针对已知的数组,我们可以通过记录历史的第一、第二大数的位置坐标,即可通过计算得到它们的生命周期以及值。
下面是代码:
def maxWindow(arr, k):
from collections import deque
queue = deque()
i = 0
result = [0] * len(arr)
while i < len(arr):
if len(queue) > 0 and i - queue[0] >= 3:
queue.popleft()
if len(queue) == 0:
queue.append(i)
elif len(queue) == 1:
if arr[queue[-1]] <= arr[i]:
queue.pop()
queue.append(i)
else:
while len(queue) > 0 and arr[queue[-1]] <= arr[i]:
queue.pop()
queue.append(i)
result[i] = arr[queue[0]]
i += 1
return result
那么,针对流式数据应该如何处理呢?同样采取以上方法即可。
显然,通过记录位置下标的方法不可用了。那么我们只有记录并更新历史k中最大两个数的生命周期了。
代码如下:
class MaxWindow:
def __init__(self, k):
self.k = k
self.a, self.b = None, None
self.a_life, self.b_life = 0, 0
def max(self, num):
if self.a_life >= self.k:
self.a, self.b = self.b, None
self.a_life, self.b_life = self.b_life, 0
if self.a is None:
self.a = num
self.a_life += 1
elif self.b is None:
if self.a <= num:
self.a = num
self.a_life = 1
else:
self.b = num
self.a_life += 1
self.b_life = 1
else:
if self.a <= num:
self.a, self.b = num, None
self.a_life, self.b_life = 1, 0
elif self.b <= num:
self.b = num
self.a_life += 1
self.b_life = 1
else:
self.a_life += 1
self.b_life += 1
return self.a
t = MaxWindow(3)
for num in [1, 3, 2, 5, 4, 6, 7, 2, 1, 2, 3]:
print(t.max(num))