【问题描述】
给定一个数组,输出每个对每个位置而言左边第一个比其小的数的位置,如果不存在则输出-1。
【输入形式】
第一行一个数n<=10^5,表示数组大小。
第二行n个数,描述数组。
【输出形式】
一行n个数
【样例输入】
10
10 2 4 5 3 1 2 8 9 6
【样例输出】
-1 -1 2 3 2 -1 6 7 8 7
思路:
1.使用单调栈,用一个类保存元素的位置和数据。
当前数入栈时,所有比当前数大的元素出栈。
每次输出栈顶元素的位置后,自己进栈。
2.递归,对每个元素,找左边的邻居的比他小的元素的位置,看那个元素是不是比自己小,不断往前跳直到找到或者跳到第一个。
解决代码
方法一
#include <iostream>
#include <stack>
using namespace std;
class node{
public:
int data;
int num;
node(int data1,int num1):data(data1),num(num1){};
};
int main() {
stack<node>s;
int n=0;int input=0;int i=0;
cin>>n;
for (i=1; i<=n; i++) {
cin>>input;
node* n=new node(input,i);
while (!s.empty()&&input<s.top().data) {
s.pop();
}
if (s.empty()) {
cout<<-1<<' ';
}
else{
cout<<s.top().num<<' ';
}
s.push(*n);
}
return 0;
}
方法二
#include <iostream>
using namespace std;
int main() {
int i=0;int j=0;
int len=0;
cin>>len;
int *p=new int[len];
int *b=new int[len];
if(len==0)return 0;
for(i=0;i!=len;i++)
{cin>>p[i];
}
b[0]=-1;
for (i=1; i<len; i++) {
j=i-1;
while (p[i]<=p[j]) {
j=b[j];
if(j==-1){
break;}
}
b[i]=j;
}
for (i=0; i<len-1; i++) {
if(b[i]==-1)cout<<-1<<' ';
else cout<<b[i]+1<<' ';
}
if(b[len-1]==-1)cout<<-1;
else cout<<b[len-1]+1;
return 0;
}
反思:有序栈的使用使得思路简便很多。它可以保存以当前元素为上/下界的所有元素。