你是正确的观察到一个段是有效的 if max(segment) - min(segment) + 1 = W
。因此,问题归结为在 中找到所有长度W
段的最小值和最大值O(N)
。
为此,我们可以使用deque D
。假设我们想找到最小值。我们将在 中存储元素的索引D
,假设从 0 开始索引。让我们A
成为原始数组。
for i = 0 to N - 1:
if D.first() == i - W:
D.popFirst() <- this means that the element is too old,
so we no longer care about it
while not D.empty() and A[ D.last() ] >= A[i]:
D.popLast()
D.pushBack(i)
对于每个,这将为您提供作为 index 元素i
的最小值。[i - W + 1, i]
D.first()
popFirst()
从 中删除第一个元素D
。当 中的第一个元素距离D
超过步时,我们必须这样做,因为它不会对上述区间中的最小值做出贡献。W
i
popLast()
从 中删除最后一个元素D
。我们这样做是为了保持排序顺序:如果 in 的最后一个元素D
是大于 的元素的索引A[i]
,那么i
在末尾添加D
会破坏顺序。所以我们必须不断删除最后一个元素以确保D
保持排序。
pushBack()
在末尾添加一个元素D
。添加后,D
肯定会保持排序。
这是O(1)
(要找到一个最小值,上面的伪代码是O(n)
),因为每个元素最多会被推送和弹出D
一次。
这是有效的,因为D
它将始终是一个按其关联值排序的索引的滑动窗口A
。当我们在一个会破坏这个顺序的元素处时,我们可以从D
(滑动窗口)弹出元素,直到恢复顺序。由于新元素比我们弹出的元素小,因此这些元素无法为解决方案做出贡献。
请注意,即使没有我使用的方法,您也可以通过保持两个与D
:start
和. 关联的指针来实现这一点end
。然后制作D
一个长度数组,N
你就完成了。