1. 程式人生 > 其它 >leetcode 239 滑動視窗最大值

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 };