Python 求给定大小的每个相邻子阵的最大值
我试图用Python解决以下问题 给定一个数组和一个整数k,求每个大小为k的连续子数组的最大值 这个想法是使用一个双端队列。这是我的代码:Python 求给定大小的每个相邻子阵的最大值,python,algorithm,data-structures,queue,Python,Algorithm,Data Structures,Queue,我试图用Python解决以下问题 给定一个数组和一个整数k,求每个大小为k的连续子数组的最大值 这个想法是使用一个双端队列。这是我的代码: def diff_sliding_window(arr, win): # max = -inf Q = [] win_maxes = [] # max of each window for i in range(win): print(Q) while len(Q) > 0 and arr
def diff_sliding_window(arr, win):
# max = -inf
Q = []
win_maxes = [] # max of each window
for i in range(win):
print(Q)
while len(Q) > 0 and arr[i] >= arr[len(Q) - 1]:
# get rid of the index of the smaller element
Q.pop() # removes last element
Q.append(i)
# print('>>', Q)
for i in range(win, len(arr)):
# win_maxes.append(arr[Q[0]])
print(arr[Q[0]])
while len(Q) > 0 and Q[0] <= i - win:
Q.pop()
while len(Q) > 0 and arr[i] >= arr[len(Q)-1]:
Q.pop(0)
Q.append(i)
# win_maxes.append(arr[Q[0]])
print(arr[Q[0]])
我没有得到正确的结果
更新: 我已经做了马特·蒂默曼斯建议的更改,但仍然没有得到正确的输出。对于
t2
,以及win=3
78
90
90
89 <--- should be 90
89
78
90
90
89 0和arr[i]>=arr[Q[len(Q)-1]:
#去掉较小元素的索引
Q.pop()#删除最后一个元素
Q.1(i)
#打印(“>>”,Q)
对于范围内的i(赢,蓝(arr)):
#win_maxes.append(arr[Q[0]]
打印(arr[Q[0]])
而len(Q)>0和Q[0]0以及arr[i]>=arr[Q[len(Q)-1]:
Q.popleft()
Q.1(i)
打印(arr[Q[0]])
这种方法(只需对数据进行一次传递)怎么样:
代码
输出
这种方法(只需要对数据进行一次传递)怎么样
代码
输出
下面是一个使用
itertools
和tee
的简单解决方案:
def nwise(iterable, n):
''' Step through the iterable in groups of n '''
ts = it.tee(iterable, n)
for c, t in enumerate(ts):
next(it.islice(t, c, c), None)
return zip(*ts)
def max_slide(ns, l):
return [max(a) for a in nwise(ns, l)]
>>> max_slide([1, 3, -1, -3, 5, 3, 6, 7], 3)
[3, 3, 5, 5, 6, 7]
>>> max_slide([12, 1, 78, 90, 57, 89, 56], 3)
[78, 90, 90, 90, 89]
下面是一个使用
itertools
和tee
的简单解决方案:
def nwise(iterable, n):
''' Step through the iterable in groups of n '''
ts = it.tee(iterable, n)
for c, t in enumerate(ts):
next(it.islice(t, c, c), None)
return zip(*ts)
def max_slide(ns, l):
return [max(a) for a in nwise(ns, l)]
>>> max_slide([1, 3, -1, -3, 5, 3, 6, 7], 3)
[3, 3, 5, 5, 6, 7]
>>> max_slide([12, 1, 78, 90, 57, 89, 56], 3)
[78, 90, 90, 90, 89]
看起来您正在尝试为这个问题实现O(n)算法,这比现在这里的其他两个答案要好 但是,您的实现是不正确的。当你说
arr[i]>=arr[len(Q)-1]
时,你应该说arr[i]>=arr[Q[len(Q)-1]
或arr[i]>=arr[Q[-1]
。您还交换了第二个循环中的pop
和pop(0)
案例。在你修好这些之后,它看起来是正确的
不过,您的算法不是O(n),因为您使用的是Q.pop(0)
,这需要O(k)时间。因此,您的总运行时间为O(kn)。对Q
使用deque将解决此问题
在这里,它是完全固定的,带有一些注释来说明它是如何工作的:
from collections import deque
def diff_sliding_window(arr, win):
if win > len(arr):
return []
win_maxes = [] # max of each window
#Q contains indexes of items in the window that are greater than
#all items to the right of them. This always includes the last item
#in the window
Q = deque()
#fill Q for initial window
for i in range(win):
#remove anything that isn't greater than the new item
while len(Q) > 0 and arr[i] >= arr[Q[-1]]:
Q.pop()
Q.append(i)
win_maxes.append(arr[Q[0]])
for i in range(win, len(arr)):
#remove indexes (at most 1, really) left of window
while len(Q) > 0 and Q[0] <= (i-win):
Q.popleft()
#remove anything that isn't greater than the new item
while len(Q) > 0 and arr[i] >= arr[Q[-1]]:
Q.pop()
Q.append(i)
win_maxes.append(arr[Q[0]])
return win_maxes
从集合导入数据
def差异滑动窗口(arr,win):
如果win>len(arr):
返回[]
win_maxes=[]每个窗口的最大值
#Q包含窗口中大于的项的索引
#所有项目都位于它们的右侧。这始终包括最后一项
#在窗户里
Q=deque()
#为初始窗口填充Q
对于范围内的i(赢):
#删除任何不大于新项目的内容
而len(Q)>0和arr[i]>=arr[Q[-1]]:
Q.pop()
Q.1(i)
win_maxes.append(arr[Q[0]]
对于范围内的i(赢,蓝(arr)):
#删除窗口左侧的索引(最多1个)
当len(Q)>0和Q[0]时,看起来您正在尝试为这个问题实现O(n)算法,这将比这里的其他两个答案更好
但是,您的实现是不正确的。当你说arr[i]>=arr[len(Q)-1]
时,你应该说arr[i]>=arr[Q[len(Q)-1]
或arr[i]>=arr[Q[-1]
。您还交换了第二个循环中的pop
和pop(0)
案例。在你修好这些之后,它看起来是正确的
不过,您的算法不是O(n),因为您使用的是Q.pop(0)
,这需要O(k)时间。因此,您的总运行时间为O(kn)。对Q
使用deque将解决此问题
在这里,它是完全固定的,带有一些注释来说明它是如何工作的:
from collections import deque
def diff_sliding_window(arr, win):
if win > len(arr):
return []
win_maxes = [] # max of each window
#Q contains indexes of items in the window that are greater than
#all items to the right of them. This always includes the last item
#in the window
Q = deque()
#fill Q for initial window
for i in range(win):
#remove anything that isn't greater than the new item
while len(Q) > 0 and arr[i] >= arr[Q[-1]]:
Q.pop()
Q.append(i)
win_maxes.append(arr[Q[0]])
for i in range(win, len(arr)):
#remove indexes (at most 1, really) left of window
while len(Q) > 0 and Q[0] <= (i-win):
Q.popleft()
#remove anything that isn't greater than the new item
while len(Q) > 0 and arr[i] >= arr[Q[-1]]:
Q.pop()
Q.append(i)
win_maxes.append(arr[Q[0]])
return win_maxes
从集合导入数据
def差异滑动窗口(arr,win):
如果win>len(arr):
返回[]
win_maxes=[]每个窗口的最大值
#Q包含窗口中大于的项的索引
#所有项目都位于它们的右侧。这始终包括最后一项
#在窗户里
Q=deque()
#为初始窗口填充Q
对于范围内的i(赢):
#删除任何不大于新项目的内容
而len(Q)>0和arr[i]>=arr[Q[-1]]:
Q.pop()
Q.1(i)
win_maxes.append(arr[Q[0]]
对于范围内的i(赢,蓝(arr)):
#删除窗口左侧的索引(最多1个)
而len(Q)>0和Q[0]是在引用我的解决方案时添加的“一次通过”注释吗itertools.tee
可能需要辅助存储(滑动窗口很少),但效率很高。计时使它快了30%-50%。@AChampion我当然希望是这样,因为我没有使用正确的数据结构(=在result
中使用数组的代码非常未优化,尤其是k_max
)。别误会,我喜欢函数式编程和itertools。但有时其他的东西更容易掌握。尽管如此:很好的代码<代码>集合。deque
确实稍微改善了一些事情。谢谢,你建立了一套iter/功能性UTIL,所以nwise
刚刚从架子上取下来,只是itertools
配方的pairwise
的一个扩展。@AChampion我没有动力优化它。但是关于collections.deque的评论非常棒(因为它专门用于我的代码所需的两个操作)!谢谢。是否在我的解决方案中添加了“一次通过”评论itertools.tee
可能需要辅助存储(滑动窗口很少),但效率很高。计时使它快了30%-50%。@AChampion我当然希望是这样,因为我没有使用正确的数据结构(=在result
中使用数组的代码非常未优化,尤其是k_max
)。别误会,我喜欢函数式编程和itertools。但有时其他的东西更容易掌握。尽管如此:很好的代码<代码>集合。deque
确实稍微改善了一些事情。谢谢,您建立了一套iter/功能UTIL,因此nwise
刚刚从架子上取下,并且只是itertools的pairwise
的扩展<
def nwise(iterable, n):
''' Step through the iterable in groups of n '''
ts = it.tee(iterable, n)
for c, t in enumerate(ts):
next(it.islice(t, c, c), None)
return zip(*ts)
def max_slide(ns, l):
return [max(a) for a in nwise(ns, l)]
>>> max_slide([1, 3, -1, -3, 5, 3, 6, 7], 3)
[3, 3, 5, 5, 6, 7]
>>> max_slide([12, 1, 78, 90, 57, 89, 56], 3)
[78, 90, 90, 90, 89]
from collections import deque
def diff_sliding_window(arr, win):
if win > len(arr):
return []
win_maxes = [] # max of each window
#Q contains indexes of items in the window that are greater than
#all items to the right of them. This always includes the last item
#in the window
Q = deque()
#fill Q for initial window
for i in range(win):
#remove anything that isn't greater than the new item
while len(Q) > 0 and arr[i] >= arr[Q[-1]]:
Q.pop()
Q.append(i)
win_maxes.append(arr[Q[0]])
for i in range(win, len(arr)):
#remove indexes (at most 1, really) left of window
while len(Q) > 0 and Q[0] <= (i-win):
Q.popleft()
#remove anything that isn't greater than the new item
while len(Q) > 0 and arr[i] >= arr[Q[-1]]:
Q.pop()
Q.append(i)
win_maxes.append(arr[Q[0]])
return win_maxes