Monotonic-stack
单调栈可以用来求在一个数组中,位置i
上的数左右离它最近的且比i位置上的数大(或小)的第一个数。首先,如果要求最近且比位置i
上的数大,那么就要维持一个从栈底到栈顶由大到小的状态。如果新进来的数大于栈顶的数,那么栈顶数x
右边最大的数就是即将新进来的数。x
左边的最大的数就是栈顶地下的数。(这适用于数组中没有重复的数字)。
如果有重复值,那么栈中就不存放下标了,存放一个数组(保存的是大小相同的元素下标),每次弹出时,左边最近比它的是它下边队列后的最后一个下标位置的元素。
``` c++ "数组中无重复元素" //单调栈结构,求解i位置上左右离他最近且比它小的值 struct MonotonicStack { stack mono; //返回一个二维数组,每一行表示该位置左右离它最近的数,0左1右 vector> GetNearLessNoRepeat(vector& nums) { if (nums.empty()) { return vector> {}; } //一定要先开辟空间,否则无法使用下标 vector> results(nums.size(),vector(2)); //处理每个位置上的元素 for (int i = 0; i < (int)nums.size(); ++i) { //单调栈,栈底到栈顶,由小到大 while (!mono.empty() && nums[mono.top()] > nums[i]) { //栈不空,且栈顶元素比即将入栈的元素大,破坏了有大到小的结构(从栈顶到栈底) int current = mono.top(); mono.pop(); results[current][1] = i; results[current][0] = mono.empty() == true ? -1 : mono.top(); } //栈不为空且栈顶元素小于nums[i] mono.push(i); } //如果栈不为空,还需结算处理 while (!mono.empty()) { int popIndex = mono.top(); mono.pop(); results[popIndex][1] = -1; results[popIndex][0] = mono.empty() == true ? -1 : mono.top(); } return std::move(results); }
``` c++ "数组有重复元素"
vector<vector<int>> GetLessRepeat(vector<int>& nums) {
if (nums.empty()) {
return vector<vector<int>>{};
}
stack<vector<int>> mono;
vector<vector<int>> results(nums.size(),vector<int>(2));
for (int i = 0; i < (int)nums.size(); ++i) {
//比是和第一个元素比,求最左时是最后一个元素
while (!mono.empty() && nums[mono.top().front()] > nums[i]) {
vector<int> current_sets = mono.top();
mono.pop();
//弹栈时需要求每个元素的最左最右值
for (auto elem : current_sets) {
results[elem][1] = i;
results[elem][0] = mono.empty() == true ? -1 : mono.top().back();
}
}
//插入时要看是和top相等还是比top大
if (!mono.empty() && nums[mono.top().back()] == nums[i]) {
mono.top().push_back(i);
}
//比栈顶大或者为空,那就直接压栈就完事了
else {
mono.push(vector<int>{i});
}
}
//清零操作
while (!mono.empty()) {
auto temp = mono.top();
mono.pop();
for (auto elem : temp) {
//如果栈不为空,可以先取栈顶元素,避免多次访问栈
results[elem][1] = -1;
results[elem][0] = mono.empty() == true ? -1 : mono.top().back();
}
}
return std::move(results);
}
Last updated
Was this helpful?