題目:
思路:
窗口進行滑動時,需要快速獲取min和max,因此需要一個結構來保存最值,而不是臨時計算。動態的最值更新容易聯想到單調棧,但是這里需要頻繁增刪元素,因此用雙端隊列,front刪除移除窗口的元素,back增添移入窗口的元素。
創建兩個雙端隊列,一個記錄窗口最小值,一個記錄窗口最大值。
最小值雙端隊列中遞增排序,首元素就是當前窗口中的最小值。每次窗口移動1位,首先判斷位于隊首的元素是否被移除窗口,如果是,出隊,否則將新元素與隊尾元素比較,如果大于隊尾元素直接入隊,否則將隊尾元素出隊,直至新元素入隊,作為備選的最小值。
最大值雙端隊列中遞減排序,其他操作與最小值雙端隊列類似。
代碼:
#include<iostream>
#include<vector>
#include<deque>
using namespace std;void slidingWindow(const vector<int>& arr, int k, vector<int>& mins, vector<int>& maxs)
{deque<int> min_q, max_q;for (int i = 0; i < arr.size(); i++){//移除不在窗口中的元素while (!min_q.empty() && min_q.front() <= i - k)min_q.pop_front();while (!max_q.empty() && max_q.front() <= i - k)max_q.pop_front();//維護最小值隊列while (!min_q.empty() && arr[i] <= arr[min_q.back()])min_q.pop_back();min_q.push_back(i);//維護最大值隊列while (!max_q.empty() && arr[i] >= arr[max_q.back()])max_q.pop_back();max_q.push_back(i);//當窗口形成時記錄結果if (i >= k - 1){mins.push_back(arr[min_q.front()]);maxs.push_back(arr[max_q.front()]);}}
}int main()
{int n, k;cin >> n >> k;vector<int> arr(n);for (int i = 0; i < n; i++)//獲取數組cin >> arr[i];vector<int> mins, maxs;slidingWindow(arr, k, mins, maxs);for (int num : mins)cout << num << " ";cout << endl;for (int num : maxs)cout << num << " ";cout << endl;return 0;
}
?運行結果: