单调栈结构解决的问题:
一个数组中有一些数:5, 4, 6, 7, 2, 3, 0, 1
我想知道每个数他的左边最近的比他大的和他的右边最近的比他大的,要求时间复杂度O(N)
栈底 -> 栈顶 维持由大到小的单调性
从左向右将遍历数组,如果元素小于栈顶元素,加入。
如果大于等于:
1)栈顶元素弹出。
2)此时栈顶元素的左边最近的比他大的数是当前栈顶元素,栈顶元素的右边最近的比它大的数是遍历数组的当前元素。
3)继续遍历当前元素。
遍历完数组后栈不为空,进入清算阶段:
依次弹出栈顶元素,栈顶元素左边最近的比他大的数是它压着的元素,无右边最近的比它大的数。
vector<vector<int>> leftRightMostMax(vector<int>& arr){
vector<int> leftMax (arr.size(), -9);
vector<int> rightMax (arr.size(), -9);
stack<int> stack;
for(int i = 0; i < arr.size(); i++){
if(stack.empty()){
stack.push(i);
}
else{
if(arr[stack.top()] > arr[i]){
stack.push(i);
}
else{
while(!stack.empty() && arr[stack.top()] < arr[i]){
int temp = stack.top(); stack.pop();
rightMax[temp] = i;
leftMax[temp] = stack.empty() ? -1 : stack.top();
}
stack.push(i);
}
}
}
while(!stack.empty()){
int temp = stack.top(); stack.pop();
rightMax[temp] = -1;
leftMax[temp] = stack.empty() ? -1 : stack.top();
}
vector<vector<int>> ans;
ans.push_back(leftMax);
ans.push_back(rightMax);
return ans;
}
数组中有重复值时:
栈底 -> 栈顶 维持由大到小的单调性
从左向右将遍历数组,如果元素小于栈顶元素,加入。
如果大于:
1)栈顶元素弹出。
2)此时栈顶元素的左边最近的比他大的数是当前栈顶元素,栈顶元素的右边最近的比它大的数是遍历数组的当前元素。
3)继续遍历当前元素。
如果等于:将当前元素与栈顶元素合为一个元素(含原两个元素的下标),加入栈。