Description
Given an array of n integer with duplicate number, and a moving window(size k), move the window at each iteration from the start of the array, find the maximum number inside the window at each moving.
Have you met this question in a real interview?
Example
For array [1, 2, 7, 7, 8], moving window size k = 3. return [7, 7, 8]
At first the window is at the start of the array like this
[|1, 2, 7| ,7, 8] , return the maximum 7;
then the window move one step forward.
[1, |2, 7 ,7|, 8], return the maximum 7;
then the window move one step forward again.
[1, 2, |7, 7, 8|], return the maximum 8;
Challenge
o(n) time and O(k) memory
最好的解法应该是用单调递减队列,因为是求最大值(如果求最小值用单调递增对列)。这里递减是说从deque的front()到back()递减。
注意判断条件:
- (nums[i] > nums[dq.back()]) 适用于单调递减队列
而 (nums[i] < nums[dq.back()]) 适用于单调递增队列 - (i - dq.front() == k) 用来决定pop掉front()的元素。注意不能用dq.size()==k,因为有些元素已经在最开始的while()循环就pop_back,所以没有算进window size,结果当然不对。
class Solution {
public:
/**
* @param nums: A list of integers.
* @param k: An integer
* @return: The maximum number inside the window at each moving.
*/
vector<int> maxSlidingWindow(vector<int> &nums, int k) {
int len = nums.size();
vector<int> result;
if ((len <= 0) || (len < k)) return result;
deque<int> dq; // non-increasing list, as it needs maximum (otherwise, non-decreasing list for minimum)
for (int i = 0; i < len; ++i) {
while (!dq.empty() && (nums[i] > nums[dq.back()])) { //for non-increasing, use > here; for non-decreasing, use < here
dq.pop_back();
}
dq.push_back(i);
if (i - dq.front() == k) {
dq.pop_front();
}
if (i >= k - 1) {
result.push_back(nums[dq.front()]);
}
}
return result;
}
};
注意,下面这种写法是错误的:
for (int i = 0; i < len; ++i) {
while (!dq.empty() && nums[i] > dq.back()) { //for non-increasing, use > here; for non-decreasing, use < here
dq.pop_back();
}
dq.push_back(nums[i]);
if (dq.size() == k) { //wrong!!!
result.push_back(dq.front());
dq.pop_front();
}
}
因为dq.size()==k并不能保证window size = k, 因为有些元素已经删掉了。所以dq里面一定要保存元素在原数组中的index!
注意:
如果是求滑动窗口移动过程中的的窗口sum的最大值,则不需要用单调队列,直接用更新maxSum即可,代码如下:
int maxFixSizeSubArray(vector<int> & nums, int k) {
int n = nums.size();
if (n < k) return 0;
int sum = 0, maxSum = 0;
for (int i = 0; i < k; ++i) {
sum += nums[i];
}
maxSum = sum;
for (int i = 1; i < n - k + 1; ++i) {
sum += nums[k + i - 1] - nums[i - 1];
maxSum = max(maxSum, sum);
}
return maxSum;
}