leetcode 239 滑动窗口最大值

不大会做,一看题解果然要用到别的数据结构。第一种方法用的是优先队列,也就是大顶堆。其中一个很好的想法是,在滑动窗口移动的时候,添加后方的元素,但是不着急删除前一个元素。而在判断最大值时,如果最大值所在的索引不在窗口内,则弹出该最大值,并重复这一段操作,直到当前最大值在窗口内。贴第一种方法

 1 class Solution {
 2 public:
 3     vector<int> maxSlidingWindow(vector<int>& nums, int k) 
 4     {
 5         vector<int> resVec;
 6         priority_queue<pair<int,int>> que;
 7         for(int i = 0 ; i < k ; i++)
 8         que.emplace(nums[i],i);
 9         resVec.push_back(que.top().first);
10         for(int i = k ; i < nums.size() ; i++)
11         {
12             que.emplace(nums[i],i);
13             while(que.top().second<=i-k)
14             que.pop();
15             resVec.push_back(que.top().first);
16         }
17         return resVec;
18     }
19 };

可以顺着这个思路进行改进。考虑某一种情况,当滑动窗口向后移动时,如果新添加的元素b大于添加之前的最后一位元素a,那就代表,如果如果a在窗口内,那么b肯定在窗口内,并且由于b大于a,则a不可能是最大值,于是就可以将a删除,之后继续进行上述操作,直到原始空间为0或者出现大于b的元素。基于上述推理,可以用一个双向队列来存放某一窗口期的下标。在完成操作后,双向队列中元素一定是单调递减的。从而可以进行最大值的选取,当前队列头即是最大值,但也需要判断最大值是否在窗口内,由此就完成了选取。贴代码

 1 class Solution {
 2 public:
 3     vector<int> maxSlidingWindow(vector<int>& nums, int k) 
 4     {
 5         vector<int> resVec;
 6         int n = nums.size();
 7         deque<int> que;
 8         for(int i = 0 ; i < k ; i++)
 9         {
10             while(!que.empty() && nums[i]>=nums[que.back()])
11             que.pop_back();
12             que.push_back(i);
13         }
14         resVec.push_back(nums[que.front()]);
15         for(int i = k ; i < n ; i++)
16         {
17             while(!que.empty() && nums[i]>=nums[que.back()])
18             que.pop_back();
19             que.push_back(i);
20             while(que.front()<=i-k)
21             que.pop_front();
22             resVec.push_back(nums[que.front()]);
23         }
24         return resVec;
25     }
26 };

还有一种方法,分治法,某一个窗口的最大值可以分为两部分,前缀部分与后缀部分。而这两部分的分界线就是当前位置索引是否是k的倍数。后缀同样有迭代公式,若n为k的倍数,则以当前节点结尾的前缀最大值就是当前节点值,若不是,则是前一节点结尾的前缀最大值和当前值的较大值。后缀有类似的递推。贴代码

 1 class Solution {
 2 public:
 3     vector<int> maxSlidingWindow(vector<int>& nums, int k) 
 4     {
 5         vector<int> resVec;
 6         int n = nums.size();
 7         vector<int> prefixMax(n),suffixMax(n);
 8         for(int i = 0 ; i < n ; i++)
 9         {
10             if(i%k == 0)
11             prefixMax[i] = nums[i];
12             else
13             prefixMax[i] = max(prefixMax[i-1],nums[i]);            
14         }
15         for(int i = n-1 ; i >= 0 ; i--)
16         {
17             if(i == n-1 || (i+1)%k == 0)
18             suffixMax[i] = nums[i];
19             else
20             suffixMax[i] = max(suffixMax[i+1],nums[i]);
21         }
22         for(int i = 0 ; i <= n-k ; i++)
23         resVec.push_back(max(suffixMax[i],prefixMax[i+k-1]));
24         return resVec;
25     }
26 };

 

上一篇:2021-10-5 239. 滑动窗口最大值(单调队列)


下一篇:239. 滑动窗口最大值