day19, 滑动窗口最大值
题目来源:leetcode
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。
返回滑动窗口最大值。
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[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
注意:你可以假设 k 总是有效的,1 ≤ k ≤ 输入数组的大小,且输入数组不为空。
解答:为了达到线性时间,需要使用堆(优先队列)来实现。
首先,先将指针从数组头走到第一个滑动窗口大小处,期间,将所有的元素放入堆中,输出第一个最大的元素。随后,逐个遍历,如果最大元素在滑动窗口中,则将目前元素入堆,输出最大元素,向下走;否则,将所有在滑动窗口外的最大元素从堆中去除,之后输出最大元素,继续向下走。
代码:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if( nums.size() == 0)
return nums;
priority_queue< pair<int,int> > notes;
pair<int, int> record[nums.size()];
vector<int> result;
for( int i = 0; i <nums.size(); i++)
record[i].first = nums[i], record[i].second = i;
for( int i = 0; i < k && i < nums.size(); i++)
notes.push( record[i]);
result.push_back( notes.top().first);
for( int i = k; i < nums.size(); i++){
if( i - k < notes.top().second){//最大值在滑动窗口中
notes.push( record[i]);
result.push_back( notes.top().first);
}
else{
while( !notes.empty() && notes.top().second <= i - k)
notes.pop();
notes.push( record[i]);
result.push_back( notes.top().first);
}
}
return result;
}
运行结果: