单调栈
利用单调栈寻找当前值在数组中的某段作为最小(大)值左可扩展的最大距离
时间复杂度为O(n)。遍历原数组,维护单调栈。以当前数在数组某一段中作为最小值为例:
先找向右可扩展的最远编号,按从前往后的顺序数组中的值进栈,如果新进值大于栈顶元素值,进栈。否则一直删除栈顶元素一直到当前编号可以入栈(大于栈顶元素)。在每个元素出栈的时候,就是每个元素可向右扩展的最远距离的时候,记录下来。找向左扩展最远编号则从右向左以相同方式找。
作为最大值找,相同
a: 2 1 5 3 7 2 8
l : 1 1 3 3 5 3 7
r : 1 7 3 5 5 7 7
#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;
const int maxn = 100000 + 10;
int n;
long long a[maxn], l[maxn], r[maxn];
int main()
{
while(scanf("%d", &n) != EOF && n){
for(int i = 1; i <= n; i++) scanf("%I64d", &a[i]);
stack<int> s;
for(int i = 1; i <= n; i++){
if(s.empty() || a[s.top()] <= a[i]) s.push(i); //作为最小值,并且如果相等可继续扩展,(可修改)
else{
while(!s.empty() && a[s.top()] > a[i]){
r[s.top()] = i - 1;
s.pop();
}
s.push(i);
}
}
while(!s.empty()){
r[s.top()] = n;
s.pop();
}
for(int i = n; i > 0; i--){
if(s.empty() || a[s.top()] <= a[i]) s.push(i);
else{
while(!s.empty() && a[s.top()] > a[i]){
l[s.top()] = i + 1;
s.pop();
}
s.push(i);
}
}
while(!s.empty()){
l[s.top()] = 1;
s.pop();
}
printf("\n");
for(int i = 1; i <= n; i++) printf("%I64d ",l[i]); printf("\n");
for(int i = 1; i <= n; i++) printf("%I64d ",r[i]); printf("\n");
}
return 0;
}