开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情
输出每个数左边第一个比它大的数
做法:如果当前数比栈顶大,因为它更靠右,所以栈顶就没用了
- 当前数>=栈顶元素,弹出栈顶元素, 不断处理,直到栈为空 或者 当前数< 栈顶元素
- 如果栈为空,那么当前数的左边第一个比它大的数就不存在,它本身就是当前[0,i]范围元素的最大值
- 如果当前数< 栈顶元素 ,那么此时的栈顶元素就是左边第一个比当前元素大的数
//输出每个数左边第一个比它大的数
#include <iostream>
using namespace std;
const int N = 1e5 + 5;
int n, x, tt = -1, s[N]; // tt==-1:表示栈为空
int main()
{
cin >> n;
while (n --)
{
cin >> x;
//如果当前数比栈顶大,因为它更靠右,所以栈顶元素就没用了
while (tt != -1 && s[tt] <= x) tt --;
cout << (tt != -1 ? s[tt] : -1) << ' ';
s[++ tt] = x;
}
return 0;
}
输出每个数右边第一个比它小的数
做法1:逆序遍历,如果当前数比栈顶小,因为它更靠左,所以栈顶就没用了
- 当前数<=栈顶元素,弹出栈顶元素, 不断处理,直到栈为空 或者 当前数> 栈顶元素
- 如果栈为空,那么当前数的右边第一个比它小的数就不存在,它本身就是当前[i,n-1]范围元素的最小值
- 如果当前数> 栈顶元素 ,那么此时的栈顶元素就是右边第一个比当前元素小的数
//输出每个数右边第一个比它小的数
#include <iostream>
using namespace std;
const int N = 1e5 + 5;
int n, tt = -1,s[N], a[N];
int main() {
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
//逆序遍历,如果当前数比栈顶小,因为它更靠左,所以栈顶就没用了,维护单调递减的栈
for (int i = n - 1; i >= 0; i --)
{
while (tt!=-1 && s[tt] >= a[i]) tt --;
a[i] = tt ? s[tt - 1] : -1;
s[++ tt] = a[i];
}
for (int i = 0; i < n; i ++) cout << a[i] << ' ';
return 0;
}
做法2:先逆序,转化为求左边第一个比它小的数,再逆序输出
//求每个数右边第一个比它小的数 等价于 逆序之后,求左边第一个比它小的数
#include <iostream>
using namespace std;
const int N = 1e5 + 5;
int n, tt = -1, s[N], a[N];
int main()
{
cin >> n;
for (int i = n - 1; i >= 0; i --) cin >> a[i];
//求左边第一个比它小的数
for (int i = 0; i <= n; i ++)
{
//如果当前数比栈顶小,因为它更靠右,所以栈顶就没用了
while (tt != -1&& s[tt] >= a[i]) tt --;
a[i] = tt ? s[tt - 1] : -1;
s[++ tt] = a[i];
}
//逆序输出答案
for (int i = n - 1; i >= 0; i --) cout << a[i] << ' ';
return 0;
}