Question: A long array A[] is given to you. There is a sliding window of size w, which is moving from the very left of the array to the very right. You can only see the w numbers in the window. Each time the sliding window moves rightwards by one position.
Example: The array is [1 3 -1 -3 5 3 6 7], and w is 3.
Input: A long array A[], and a window width w
Output: An array B[], B[i] is the maximum value of from A[i] to A[i+w-1]
Answer: The obvious solution with run time complexity of O(nw) is definitely not efficient enough. Every time the window is moved, we have to search for the maximum from w elements in the window.
We need a data structure where we can store the candidates for maximum value in the window and discard the element, which are outside the boundary of window. For this, we need a data structure in which we can edit at both the ends, front and back. Deque is a perfect candidate for this problem.
We are trying to find a way in which, we need not search for maximum element among all in the window. We will make sure that the largest element in the window would always appear in the front of the queue.
Every time, we move to a new window, we will be getting a new element and leave an old element. We should take care of:
Code:
Complexity: Each element in the list is being inserted and then removed at most once. Therefore, the total number of insert and delete operations is 2n. Therefore it is an O(n) solution.
Window position Max --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
Input: A long array A[], and a window width w
Output: An array B[], B[i] is the maximum value of from A[i] to A[i+w-1]
Answer: The obvious solution with run time complexity of O(nw) is definitely not efficient enough. Every time the window is moved, we have to search for the maximum from w elements in the window.
We need a data structure where we can store the candidates for maximum value in the window and discard the element, which are outside the boundary of window. For this, we need a data structure in which we can edit at both the ends, front and back. Deque is a perfect candidate for this problem.
We are trying to find a way in which, we need not search for maximum element among all in the window. We will make sure that the largest element in the window would always appear in the front of the queue.
While traversing the array in forward direction if we find a window where element A[i] > A[j] and i > j, we can surely say that A[j], will not be the maximum element for this and succeeding windows. So there is no need of storing j in the queue and we can discard A[j] forever.For example, if the current queue has the elements: [4 13 9], and a new element in the window has the element 15. Now, we can empty the queue without considering elements 4, 13, and 9, and insert only element 15 into the queue.
Every time, we move to a new window, we will be getting a new element and leave an old element. We should take care of:
- Popping elements outside the window from queue front.
- Popping elements that are less than new element from the queue.
- Push new element in the queue as per above discussion.
Window position Queue content Max --------------- ------------- -----[1 3 -1] -3 5 3 6 7 3 -1 3 1 [3 -1 -3] 5 3 6 7 3 -1 -3 3 1 3 [-1 -3 5] 3 6 7 5 5 1 3 -1 [-3 5 3] 6 7 5 3 5 1 3 -1 -3 [5 3 6] 7 6 6 1 3 -1 -3 5 [3 6 7] 7 7
Code:
#include<deque> void maxSlidingWindow(int A[], int n, int w, int B[]) { deque<int> Q; //Initilize deque Q for first window for (int i = 0; i < w; i++) { while (!Q.empty() && A[i] >= A[Q.back()]) Q.pop_back(); Q.push_back(i); } for (int i = w; i < n; i++) { B[i-w] = A[Q.front()]; //update Q for new window while (!Q.empty() && A[i] >= A[Q.back()]) Q.pop_back(); //Pop older element outside window from Q while (!Q.empty() && Q.front() <= i-w) Q.pop_front(); //Insert current element in Q Q.push_back(i); } B[n-w] = A[Q.front()]; }
Complexity: Each element in the list is being inserted and then removed at most once. Therefore, the total number of insert and delete operations is 2n. Therefore it is an O(n) solution.
Subscribe - To get an automatic feed of all future posts subscribe here, or to receive them via email go here and enter your email address in the box. You can also like us on facebook and follow me on Twitter @akashag1001.
Very nice solution! But I think in your code the "O" should be "Q".
@天意 : Thanks! Seems you are talking about queue name. It's 'Q' only. Sometimes on chrome, it doesn't show the last few pixels in a line. That might be the reason, it is visible as 'O'.
Hi Akash.... do you really mean B[i-w]=A[Q.front()] because Q.front() will not be same as the index of maximum number in the particular window of array A
Hey Akash...i got it.... you are pushing i...i thought u were pushing a[i]...i got it thnk u.
@Akash Please Explain 1st initialize part what are doing ? what the content of windows os size 3 after that for our array 1,3,-1,-3,5,3,6,7}
also what A[Q.back()] will return is it index or value at that index ?
as you are pushing index in queue using Q.push_back(i);
please click here http://ideone.com/KLIpO & explain me
i have some confusion so please reply
@Anonymous: Since Q has just indexes than Q.back() will also be an index. It means that A[Q.back()] will be the value at Q.back() position.
I couldn't get your first question?
@akash i am asking about this part
# //Initilize deque Q for first window
# for (int i = 0; i < w; i++)
# {
# while (!Q.empty() && A[i] >= A[Q.back()])
# Q.pop_back();
# Q.push_back(i);
# }
can you tell me what will be the content of queue after exceuting aboce code for window of size 3 for this array
1,3,-1,-3,5,3,6,7}
this will make my whole confusion clear :)
Thanks
@Anonymous: Though this could easily be be found in debugging but since U asked the answer will be:
Q contents will be (3, -1) after that step.
This just simulates insert sort in the queue. I don't see any O(n) algorithm.
@Anonymous: Why do you think, it's not an O(n) solution?
@Akash So you are maintaining indexes in the DQueue right.. It took me some time to figure that out :-) I was wondering how were you able to remove the older element outside window from Q if it were actual element instead of indexes... May be you can update the comments , instead of element you can mention element's index!
@Akash
//Pop older element outside window from Q
while (!Q.empty() && Q.front() <= i-w)
Q.pop_front();
where ist needed , plz explain , i am still not getting
@anonymous: At any time, queue should only contain element inside the current window. That's the reason, I am popping illegitimate element from the queue.
Binary search could also be used to clip off the suffix of the ring buffer.
What if it was -5 instead of 5? Is this solution really correct?
Nevermind. Got it. Q is storing indices, not values..
Good post! We are linking to this particularly great post on our websites.
educatorpage
Bloglovin
gumroad
toparticle
door site
Zenwriting
You wrote an amazing article. I am amazed, your efforts are shown in the article. I hope in future I will see more Articles from you.
-Custom Website Design
This post is very beautiful and well-maintained, and it deserves to be recognised. Thank you for your time and effort, and please continue to update.Web Design Company USA
I adore your work, and it greatly motivates me.
Software Testing Services
This is just what I was looking for. Thank you for sharing this essential information. It is quite beneficial.
QA Testing Services
Great information.