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.
Following is an example:The array is [1 3 -1 -3 5 3 6 7], and w is 3.
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.
public static Integer[] getMaxInSlideWindow(Integer[] A, Integer w) {
// invalid input
if (A == null || w <= 0 || A.length - w < 0) return null;
Integer[] B = new Integer[A.length - w + 1];
// auxiliary queue that is sorted in descending order
LinkedList<Integer> q = new LinkedList<Integer>();
for (int i = 0; i < A.length; i++) {
// enqueue. Remove those smaller values
int data = A[i];
while (!q.isEmpty() && q.getLast() < data) {
q.removeLast();
}
q.add(data);
if (i < w - 1) continue;
// dequeue. If the current number is the maximum. Also remove it
// from the queue
B[i - w + 1] = q.get(0);
if (A[i - w + 1] == B[i - w + 1]) {
q.removeFirst();
}
}
return B;
}
The above algorithm could be proven to have run time complexity of O(n). This is because each element in the list is being inserted and then removed at most once. Therefore, the total number of insert + delete operations is 2n.
参考:http://www.leetcode.com/2011/01/sliding-window-maximum.html
http://tech-queries.blogspot.com/2011/05/sliding-window-maximum.html