时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
有N个蚂蚁兄弟从左到右排成一行,每个蚂蚁见到比自己岁数大的蚂蚁就称为大哥。现在每只蚂蚁都先左看,寻找最近的大哥。找不到时输出0。
请编一个程序,帮助蚂蚁们计算每只蚂蚁的最近大哥是哪个?
输入
第一行2个正整数:N,N的范围是[1…100000]。
第二行:N个正整数,表示每只蚂蚁的年龄,每个数的范围是[0…1,000,000,000]。
输出
一行,N个整数,表示相应蚂蚁的最近大哥的编号。编号从1到N。
样例输入 Copy
6
8 6 3 3 5 1
样例输出 Copy
0 1 2 2 2 5
题意很简单,就是求数组中任意元素的左边首次出现的比它大的元素的编号,如果找不到就输出0。
一开始我寻找后一个元素与前一个元素的大小关系,结果WA了。。。
后来想了很久,没有思路,上网查阅解决这类问题的相关资料后得知采用栈来处理,而且是单调栈。
单调栈就是栈底到栈顶的元素按升序或降序排列的栈,在普通的栈的基础上对进栈元素有了要求——必须单调。
这个题我们可以采用栈底到栈顶元素降序排列的单调栈。先遍历数组,如果栈为空,则元素进栈;如果栈不为空且当前元素不小于栈顶元素,栈顶元素出栈,直到当前元素大于等于栈顶元素。该循环结束后,一定满足当前元素大于等于栈顶元素,因此当前元素进栈,同时注意到此时的栈顶元素就是当前元素的左边首次出现的比它大的元素。
接下来就是我感觉比较麻烦的地方。。。
题目要输出编号,在遍历、进栈、出栈的过程中,不方便用一个变量记录栈顶元素的编号,实现起来及其麻烦。如果我们用一个结构体记录元素的大小和编号,并且定义一个结构体类型的栈,这个问题就能完美解决。
#include<cstdio>
#include<stack>
using namespace std;
struct ant
{
int age;
int index;
}a[100005];
stack<ant>num;//结构体类型的栈
int ans[100005];
int main()
{
int n,i;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i].age);//大小
a[i].index=i;//编号
}
for(i=1;i<=n;i++)
{
while(!num.empty()&&a[i].age>=num.top().age)//为保证单调栈,先弹出不满足单调型的元素,最后再进栈
{
num.pop();
}
if(!num.empty())//存在栈顶元素比当前元素大
{
ans[i]=num.top().index;
}
else//栈为空,则找不到栈顶元素比当前元素大
{
ans[i]=0;
}
num.push(a[i]);
}
for(i=1;i<=n;i++)
{
printf("%d",ans[i]);
if(i<n)printf(" ");
}
return 0;
}
/**************************************************************
Language: C++
Result: 正确
Time:47 ms
Memory:3116 kb
****************************************************************/