一、题目
二、解题思路:
- 题意为让我们找到每个元素的左边第一个比它小的元素,若不存在则输出
-1
2.1法一:暴力(0n2)
- 首先,我们可以想到最朴素的算法:直接暴力
两层for
达成目标 - 核心代码如下:
int n;cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
memset(l,-1,sizeof l);
for(int i=1;i<=n;i++) //遍历
{
for(int j=i-1;j>=1;j--) //从i开始往左找目标值,
{
if(a[j]<a[i]) //表示找到了
{
l[i]=a[j];
break;
}
}
}
for(int i=1;i<=n;i++) cout<<l[i]<<' ';
也就是对于每一个元素,都往前去找对应的元素
2.2:单调栈
- 如果
(mid)
<st.top()
则表明此时的mid
一定的更优的,也就意味着此时st.top()
它一定不可能成为答案,因此我们可以把它删掉st.pop()
*也就是说只要一个元素是小于栈顶元素的,那么它的左边元素就全部作废(不会对结果产生印象),一个while
即可
-
2、因此我们可以来模拟单调栈的过程
- 1):此时栈为空,所以
7-->-1
,并且让7进栈
*2):此时,8(mid)
想进来,可以发现st.top()<mid
,因此,st.top
一定就是8
左边离它最近且比它小的元素。接着让8
入栈
- 3):接下来轮到
5(mid)
,可以发现此时mid<st.top()
,因此,应该对st
进行修改,让mid>st.top()
。可以用while
来实现,一直让st.pop()
直到mid>st.top()
,接着让mid
入栈
因此可以总结出我们的规则
三、完整代码如下:
PS:也可以使用数组来模拟栈的过程
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 7; // 定义最大范围
int a[N],l[N];
void solve()
{
memset(l,-1,sizeof l);
int n; cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
stack<int>st; //存储序列下标
for (int i = 1; i <= n; i++)
{
while (!st.empty() && a[st.top()] >= a[i]) //非空 且 栈顶元素>=a[i]
{
st.pop();//出栈
}
if (st.empty())
{
l[i] = -1; //此时栈为空,则表示没有比a[i]更小的数
}
else if (a[st.top()] < a[i]) //否则此时栈顶元素就是距离a[i]最近的小于元素
{
l[i] = a[st.top()]; //那么此时栈顶元素即是符合条件的
}
st.push(i); //入栈
}
for (int i = 1; i <= n; i++) cout << l[i] << ' ';
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _ = 1; //cin >> _;
while (_--) solve();
system("pause");
return 0;
}