输入样例:
5 3 4 2 7 5
输出样例:
-1 3 -1 2 2
普通做法,时间复杂度O(n^2),可能会TLE
#includeusing namespace std; const int N = 1e5+10; int st[N]; int main() { int n,x; int res; scanf("%d", &n); for (int i = 0; i < n; i ++ ) { scanf("%d", &st[i]); int ret = 0; for(int j = i-1; j >= 0; j --){ if(st[j] < st[i]){ ret = 1; res = st[j]; break; } } if(ret) printf("%d ",res); else printf("-1 "); } return 0; }
单调栈,时间复杂度O(n)
保证每次输出时,栈顶均为该位置前的最小数
(与上一种做法相比,去除了大量重复且无意义的步骤,每个数只会进出栈一次,而上一种做法双重循环会使得很多数被反复遍历)
#includeusing namespace std; const int N = 1e5+10; int st[N],top;//栈 int main() { int n,x; scanf("%d", &n); for (int i = 0; i < n; i ++ ) { scanf("%d", &x); while(top && st[top]>=x) top--; if(!top) printf("-1 "); else printf("%d ",st[top]); st[++top] = x; } return 0; }
154. 滑动窗口 - AcWing题库高质量的算法题库https://www.acwing.com/problem/content/description/156/
不断进出队列, 保证输出的时候队列的队头存着当前窗口最小/最大值 在数组a中的下标
#includeusing namespace std; const int N = 1e6+10; int a[N],q[N]; int main() { int n, k; cin >> n >> k; for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); int h = 0, t = -1;//h-队头下标, t-队尾下标 for (int i = 0; i < n; i ++ ) { if(h <= t && i+1-k > q[h]) h++; while(h <= t && a[i] <= a[q[t]]) t--; q[++t] = i; if(i >= k-1) printf("%d ",a[q[h]]); } cout << endl; h = 0, t = -1; for (int i = 0; i < n; i ++ ) { if(h <= t && i+1-k > q[h]) h++; while(h <= t && a[i] >= a[q[t]]) t--; q[++t] = i; if(i >= k-1) printf("%d ",a[q[h]]); } return 0; }
我们可以调试一下看一看各个变量的变化情况,这个过程会更加清晰明了
#includeusing namespace std; const int N = 1e6+10; int a[N],q[N]; int main() { int n, k; cin >> n >> k; for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); int h = 0, t = -1;//h-队头下标, t-队尾下标 for (int i = 0; i < n; i ++ ) { if(h <= t && i+1-k > q[h]) h++; while(h <= t && a[i] <= a[q[t]]) t--; q[++t] = i; // if(i >= k-1) printf("%d ",a[q[h]]); printf("i=%d, h=%d, t=%dnq[]:", i, h, t); for (int j = h; j <= t; j ++ ){ cout << a[q[j]] << ' '; } cout << endl; if(i >= k-1) printf("min=%dn",a[q[h]]); } cout << "==============" << endl; h = 0, t = -1; for (int i = 0; i < n; i ++ ) { if(h <= t && i+1-k > q[h]) h++; while(h <= t && a[i] >= a[q[t]]) t--; q[++t] = i; // if(i >= k-1) printf("%d ",a[q[h]]); printf("i=%d, h=%d, t=%dnq[]:", i, h, t); for (int j = h; j <= t; j ++ ){ cout << a[q[j]] << ' '; } cout << endl; if(i >= k-1) printf("max=%dn",a[q[h]]); } return 0; }



