题目链接:leetcode.
这题明明是困难!
而我只会用暴力,O(nk) ,O(1)
/*
执行用时:148 ms, 在所有 C++ 提交中击败了16.90%的用户
内存消耗:15.2 MB, 在所有 C++ 提交中击败了96.45%的用户
*/
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(nums.empty())
return {};
int N = nums.size();
vector<int> ans;
for(int i = 0;i <= N - k;++i)
{
int maxx = INT_MIN;
for(int j = i;j < i + k;++j)
{
maxx = max(maxx, nums[j]);
}
ans.emplace_back(maxx);
}
return ans;
}
};
· 初始时,我们将数组
nums
的前k
个元素放入优先队列中。每当我们向右移动窗口时,我们就可以把一个新的元素放入优先队列中,此时堆顶的元素就是堆中所有元素的最大值。然而这个最大值可能并不在滑动窗口中,在这种情况下,这个值在数组nums
中的位置出现在滑动窗口左边界的左侧。因此,当我们后续继续向右移动窗口时,这个值就永远不可能出现在滑动窗口中了,我们可以将其永久地从优先队列中移除。
· 我们不断地移除堆顶的元素,直到其确实出现在滑动窗口中。此时,堆顶元素就是滑动窗口中的最大值。
· 为了方便判断堆顶元素与滑动窗口的位置关系,我们可以在优先队列中存储二元组(num,index)
,表示元素num
在数组中的下标为index
。
时间复杂度:O(nlogn) 。优先队列(大根堆)插入的时间复杂度是logn
空间复杂度:O(n)
/*
执行用时:24 ms, 在所有 C++ 提交中击败了75.04%的用户
内存消耗:16.5 MB, 在所有 C++ 提交中击败了8.06%的用户
*/
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(nums.empty())
return {};
int N = nums.size();
vector<int> ans;
priority_queue< pair<int, int> > Q; //priority要拼对
for(int i = 0;i < k;++i)
{
Q.push({nums[i], i});
}
ans.push_back(Q.top().first);
for(int i = k;i < N;++i)
{
Q.push({nums[i], i});
while(Q.top().second <= i - k)
{
Q.pop();
}
ans.push_back(Q.top().first);
}
return ans;
}
};
· 使用双端队列,里面按序存储数组的下标,当新来的
j
对应的元素nums[j]
大于队尾中已有的nums[i]
时,nums[i]
就不可能是当前窗口的最大值了,将这样的下标i
从队尾弹出
· 且队首的下标应该大于等于j - k
(滑动窗口要有效),将失效的下标从队首弹出
O(n), O(k)
/*
执行用时:16 ms, 在所有 C++ 提交中击败了97.22%的用户
内存消耗:15.7 MB, 在所有 C++ 提交中击败了46.91%的用户
*/
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(nums.empty())
return {};
int N = nums.size();
vector<int> ans;
deque<int> q;
for(int i = 0;i < k;++i)
{
while(!q.empty() && nums[i] >= nums[q.back()])
{
q.pop_back();
}
q.push_back(i);
}
ans.emplace_back(nums[q.front()]);
for(int i = k;i < N;++i)
{
while(!q.empty() && nums[i] >= nums[q.back()])
{
q.pop_back();
}
q.push_back(i);
while(!q.empty() && q.front() <= i - k)
{
q.pop_front();
}
ans.emplace_back(nums[q.front()]);
}
return ans;
}
};