题目来源
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
For example,
Given nums = [1,3,-1,-3,5,3,6,7]
, and k = 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
Therefore, return the max sliding window as [3,3,5,5,6,7]
.
Note:
You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.
最直观的想法就是直接找最大的,复杂度是O(kn)。
代码如下:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
int n = nums.size();
if (n == 0)
return res;
for (int i=0; i<n-k+1; i++) {
int m = nums[i];
for (int j=i+1; j<k+i; j++)
m = max(m, nums[j]);
res.push_back(m);
}
return res;
}
};
可以AC,但是需要的时间比较多…想想还有什么办法,应该是O(n)的方法。
还没想到办法,不过可以通过保存最大值的值,通过判断最大值是不是即将退出窗口以及新进元素是否比最大值大来进行剪枝。代码如下:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
int n = nums.size();
if (n == 0)
return res;
int m = INT_MIN;
for (int i=0; i<n-k+1; i++) {
if (i > 0 && nums[i+k-1] >= m) {
res.push_back(nums[i+k-1]);
m = nums[i+k-1];
continue;
}
if (i > 0 && m != nums[i-1]) {
res.push_back(m);
continue;
}
m = nums[i];
for (int j=i+1; j<k+i; j++)
m = max(m, nums[j]);
res.push_back(m);
}
return res;
}
};
最后就是O(n)的方法了。一个很好的想法,就是当窗口中的数小于新进的数时候,可以把它pop掉。使得窗口中只保留一个index递增,值递减的一个序列。
代码如下:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
int n = nums.size();
deque<int> dq;
if (n == 0)
return res;
for (int i=0; i<n; i++) {
while (!dq.empty() && dq.front() < i - k + 1)
dq.pop_front();
while (!dq.empty() && nums[dq.back()] < nums[i])
dq.pop_back();
dq.push_back(i);
if (i >= k - 1)
res.push_back(nums[dq.front()]);
}
return res;
}
};