题目1:滑动窗口的最大值
给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。
例:
输入:[2, 3, 4, 2, 6, 2, 5, 1], 滑动窗口大小3
输出:[4, 4, 6, 6, 6, 5]
思路
- 遍历数组,每次计算滑动窗口中的最大值。
- 时间复杂度:O(mn)
- 空间复杂度:O(1)
- 遍历数组,按顺序保存当前位置窗口内的最大值,以及候选最大值。当新值进入时,从后向前判断是否大于候选最大值们,如果大于,则剔除这些候选,以新值替换,然后再剔除超出窗口的元素。
- 时间复杂度:O(n)
- 空间复杂度:O(m)
代码
思路2:时间复杂度:O(n),空间复杂度:O(m)
def max_in_sliding_window(array, window_width):
"""
:param array: numbers
:param window_width:sliding window size
:return: all max number
"""
if not array or window_width < 1:
return None
max_i = []
res = []
for i in range(len(array)):
while max_i and array[i] >= array[max_i[-1]]:
max_i.pop()
max_i.append(i)
while max_i and i - max_i[0] >= window_width:
max_i.pop(0)
if window_width - 1 <= i:
res.append(array[max_i[0]])
return res
题目2:队列的最大值
请定义一个队列并实现函数max得到队列里的最大值,要求函数max、push_back和
pop_front的时间复杂度都是O(1)。
思路
- 和题目1一样,在队列中维护一个保存最大值的队列,当pop和push操作的同时也对最大值队列进行维护。当弹出的时队列中的最大值时,也弹出最大值队列的头,当压入新值时,对最大值队列从后向前扫描剔除小于该值的元素。
- 时间复杂度:O(1)
- 空间复杂度:O(n)
代码
class Queue(object):
def __init__(self):
self.data = []
self.max_data = []
def pop(self):
"""
pop out the head element
:return: head element
"""
if not self.data:
raise Exception('Empty Queue Cannot Pop')
if self.data[0] == self.max_data[0]:
self.max_data.pop(0)
return self.data.pop(0)
def push(self, x):
"""
push in the back
:param x: element
:return: None
"""
self.data.append(x)
while self.max_data and self.max_data[-1] < x:
self.max_data.pop()
self.max_data.append(x)
return
def max(self):
"""
get the maximum element
:return: max element
"""
return self.max_data[0]
思考
利用队列先进先出的特点,可以免于考虑剔除最大值后,候补最大值不存在于队列的情况,大大减少了计算。