Why is the deque solution to the “Sliding Window Maximum” problem O(n) instead of O(nk)?

谁说我不能喝 提交于 2020-02-23 08:43:17

问题


The problem is to find the maximum in each subarray of size k in an array of length n.

The brute force method is O(nk). But using a deque, the solution is supposedly O(n). However I am not convinced that it gets to O(n), in particular because of this while loop:

# Remove all elements smaller than 
# the currently being added element  
# (Remove useless elements) 
while Qi and arr[i] >= arr[Qi[-1]] : 
    Qi.pop()

which is inside of a for loop from k to n. Couldn't this technically run up to k times each loop, giving somewhere between O(n) and O(kn)? Is the worst-case time complexity actually O(kn) even for the deque solution?


回答1:


Every element is added to the deque exactly once.

Thus you can't have more pop operations than the number of elements, which is O(n).

The while condition will sometimes be checked without a pop, but the number of times that is done is at most equal to the number of times we get to the while loop (that is, the number of iterations of both for loops), which is O(n).

The rest of the code is also O(n), thus the total running time is O(n+n+n) = O(n).




回答2:


Let's prove that the extreme worst case n * k operations is not possible (just to get the idea, and the rest in-between-ish can be proven similarly):

How to achieve n * k? At each step, we need to make k "pops" from the deque. So the elements in the deque looks like this (in this illustration, k == 5):

before:

| ,              #
| | | ,          #   (like a heavy bowling ball)
| | | | ,        #  
---------------------------------------------------             
^^^^^^^^^        ^
our deque        new badass element coming *vruuuum*

after

#
#     *bang* (sound of all pins knoked down)
#  
---------------------------------------------------             
^
this new guy totally smashed our deque in 5 operations!

but hey... wait a minute

How did our deque accumulated k elements?

Well, for it to accumulate k elements, it should throw much less in the previous k steps (otherwise the deque would be empty from the start). Crap... no n * k for ya :(


This makes a more general statement about the dynamics of our algorithm:

If ith element of the array results in m "pops" from the deque, the previous elements would sure be "lame" enough to even out the "badassness" of the ith element.

Now, if you look not from perspective of a deque but from a perspective of a whole array: each time you're throwing a unique array element. So the number of "pops" should not be greater than the number of elements in array, which is n.

Which makes our complexity O(n).




回答3:


I don't know the mathematical proof but following thought may help understanding it:

Note that indices of elements are stored in deque but for easy explanation about complexity, I'm talking in terms of elements instead of it's index.

When the new element in the window is not larger than largest element in deque (element at front of the dequeue) but larger than at least the smallest element in deque (element at rear of the deque), then we not only compare the new element with elements of deque (from rear to front) to find the right place, but also discard the elememt from deque who are smaller than the new element.

So don't see above mentioned operation as searching the right place of new element in a sorted deque of length k, instead look it as popping of deque elements smaller than the new element. Those smaller elements were added in deque at some point, the lived there for a while and now they are popped. In the worst case, each element may get this privilege of pushing into and popping from deque (although this is done alongside the operation of searching the first number from rear larger than new element and that causes all confusion).

And as each element can be pushed and popped at most once, hence the complexity is linear.




回答4:


The complexity of the algorithm is O(nk). On any of the n iterations through array, I may have to compare the new candidate element with up to O(k) elements still in the deque. The while loop inside the for loop gives it away. Consider an array of integers in descending order (of course, the algorithm doesn't have this information). Now I want to find the sliding maximum. Every element that I consider has to be put in the queue, but is incapable of displacing other elements (obviously, because it's smaller). However, I don't know this until I've removed the oldest (and largest) element, and compared the new element to all the remaining ones (ergo, k - 1 comparisons). If I wanted to use a heap as my sliding data structure, I could get the complexity down to O(n log k).

That's the worst case. Assuming the numbers are random, or effectively so within some range, each new element will displace, on average, half the k-size deque. But that's still O(nk).




回答5:


(Posting this answer after seeing conflicting comments from highly reputed SO users in https://stackoverflow.com/a/31061015/5649620)

The worst case time complexity for this question using dequeue could be detailed like:

O(n + n) // for enqueue and dequeue of each element

+

O((n/k - 1)* k) // for the repetition of accessing 'new element' to be compared with 'existing elements' in queue; where there would be n/k - 1 such 'new elements' with k 'existing elements' in queue for each in worst case.

Total: O (n + n + (n/k - 1)* k) = approx O(n)

(The second part is where normally people think that would cause the worst time complexity to be O(nk))


Example 1: // worst case

n = 30, k = 10

array: 10 9 8 7 6 5 4 3 2 1 11 10 9 8 7 6 5 4 3 2 12 11 10 9 8 7 6 5 4 3

For each of 11(first occurrence) and 12, there would be ten existing elements in queue to be compared with 11 and 12. Hence, 11 and 12 are accessed ten times each.

Here, n/k - 1 = 30/10 - 1 = 2 elements, which are 11 and 12. These would be compared with k existing elements in queue: 2 * k = 2 * 10 = 20

Example 2:

A different case could be (n = 11, k = 10): 10 9 8 7 6 5 4 3 2 1 11

Here, since only 1 element, 11, is getting repeatedly accessed with ten existing elements in queue, this would not be worser than the previous case, making the previous case the worst case.



来源:https://stackoverflow.com/questions/53094476/why-is-the-deque-solution-to-the-sliding-window-maximum-problem-on-instead-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!