代码改变世界

Sliding Window Maximum

2015-01-12 17:21  李涛的技术博客  阅读(268)  评论(0编辑  收藏  举报

(http://leetcode.com/2011/01/sliding-window-maximum.html)

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

Ouput: An array B[], B[i] is the maximum value of from A[i] to A[i+w-1]

Requirement: Find a good optimal way to get B[i]

---

1. Brute force solution is O(nw)

2. Use heap, when window moves, delete the first one in the window, add the next one into the window. The run time complexity is O(n lg w).

3. Use double-ended queue. Code:

void maxSlidingWindow(int A[], int n, int w, int B[])
{
    assert(A && n >= 0 && w >= 1 && w <= n && B);

    deque<int> Q;
    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()];
        while (!Q.empty() && A[i] >= A[Q.back()])
            Q.pop_back();
        while (!Q.empty() && Q.front() <= i-w)
            Q.pop_front();
        Q.push_back(i);
    }
    B[n-w] = A[Q.front()];
}

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 in 2n.