寻找左边第一个更小值
题目:
给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。要求:时间复杂度为O(N)
思路:
从左往右将序列中的数与栈顶元素比较,如果小于栈顶元素,则弹栈并继续比较,直到栈顶元素大于等于当前的数或栈空。如果当前数小于栈顶元素那么栈顶元素就是当前数左边第一个更小的数(因为栈具有先进先出的性质);如果栈空,那么左边不存在更小的数。接着将当前数入栈,继续遍历序列……
代码:
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
vector<int> decStack(vector<int> v1)
{
stack<int> s;
vector<int> v2;
for (auto it = v1.begin(); it != v1.end(); it++)
{
while (!s.empty() && *it < s.top())//小于则出栈继续寻找
s.pop();
if (s.empty())//如果栈空则不存在
v2.push_back(-1);
else//如果大于或等于,栈顶元素就是左边第一个比当前元素小的数
v2.push_back(s.top());
s.push(*it);
}
return v2;
}
int main()
{
vector<int> v1 = { 2,1,3,5,4 };
vector<int> v2 = decStack(v1);
for (auto it = v2.begin(); it != v2.end(); it++)
{
cout << *it << " ";
}
return 0;
}
原理:单调栈
单调栈即从栈顶至栈底单调递增或者单调递减的栈。常有如下应用场景:
(1)寻找序列数左侧第一个更小值(单调递减栈):方法如上
(2)寻找序列数左侧第一个更大值(单调递增栈):方法与上面类似,一直寻找大于序列数的栈元素,小于的出栈;或者直到栈空。然后将当前序列数入栈,继续遍历……
时间复杂度:
每个序列数至多入栈一次、出栈一次,时间复杂度为O(n)
参考:单调栈详解及其应用-CSDN博客