地址 https://www.acwing.com/problem/content/description/156/ios
輸入包含兩行。算法
第一行包含兩個整數n和k,分別表明數組長度和滑動窗口的長度。數組
第二行有n個整數,表明數組的具體數值。spa
同行數據之間用空格隔開。code
輸出包含兩個。blog
第一行輸出,從左至右,每一個位置滑動窗口中的最小值。索引
第二行輸出,從左至右,每一個位置滑動窗口中的最大值。隊列
輸入樣例: 8 3 1 3 -1 -3 5 3 6 7 輸出樣例: -1 -3 -3 -3 3 3 3 3 5 5 6 7
算法1
單調隊列
求最大值和最小值的過程實際上是同樣的 就是求極值的過程
以求最小值爲例
咱們使用一個隊列來進行記錄 處於滑動窗口的m個數字
以插入的數據的角度來看
若是插入的數據比以前的m-1個數字都小 那麼它就將清空以前的m-1個數字成爲隊首
若是插入的數據比以前m-1個數字中的某一個數字較大 那麼它在該數字退出隊列後 仍是有可能成爲最小數值的,也須要保留該插入數字,只不過插入的數字不是隊首(之後有可能成爲隊首)ip
這個隊裏有三個性質
1 隊首是最小數(以求最小值爲例)
2 隊列中隊首和隊尾數字的索引差值最大爲m,也就是控制數值在滑動窗口範圍內
3 隊列中前部的數字若是比後面的數字大,那麼在m個的滑動窗口中,它是不可能成爲最小值(隊首)的,須要排除出隊列ci
這樣就保證了隊列的單調性
該隊列記錄的是數字的索引 方便控制當前記錄的數值範圍 而不是數字的值 這個須要注意
時間複雜度
參考文獻
代碼
1 #include <iostream> 2 #include <deque> 3 #include <vector> 4 5 using namespace std; 6 7 /* 8 輸入樣例: 9 8 3 10 1 3 -1 -3 5 3 6 7 11 輸出樣例: 12 -1 -3 -3 -3 3 3 13 3 3 5 5 6 7 14 */ 15 16 17 int n, m; 18 19 int arr[1000010]; 20 deque<int> min_val, max_val; 21 vector<int> s_min, s_max; 22 23 int main() 24 { 25 cin >> n >> m; 26 27 for (int i = 0; i < n; i++) { 28 cin >> arr[i]; 29 } 30 31 32 for (int i = 0; i < n; i++) { 33 // 34 while (!min_val.empty() && ( i - min_val.front()) >= m) 35 min_val.pop_front(); 36 while (!max_val.empty() && (i - max_val.front()) >= m) 37 max_val.pop_front(); 38 39 while (!min_val.empty() && arr[min_val.back()] >= arr[i]) 40 min_val.pop_back(); 41 42 while (!max_val.empty() && arr[max_val.back()] <= arr[i]) 43 max_val.pop_back(); 44 45 min_val.push_back(i); 46 max_val.push_back(i); 47 48 s_min.push_back(min_val.front()); 49 s_max.push_back(max_val.front()); 50 } 51 52 for (int i = m - 1; i < n; i++) 53 cout << arr[s_min[i]] << " "; 54 cout << endl; 55 for (int i = m - 1; i < n; i++) 56 cout << arr[s_max[i]] << " "; 57 58 59 return 0; 60 }