leetcode 239 滑動視窗最大值
阿新 • • 發佈:2021-10-03
不大會做,一看題解果然要用到別的資料結構。第一種方法用的是優先佇列,也就是大頂堆。其中一個很好的想法是,在滑動視窗移動的時候,新增後方的元素,但是不著急刪除前一個元素。而在判斷最大值時,如果最大值所在的索引不在視窗內,則彈出該最大值,並重復這一段操作,直到當前最大值在視窗內。貼第一種方法
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 };