单调栈
一、应用场景
通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置。以空间换时间,复杂度为O(n)。
二、思路
(1)单调栈里面放的是元素下标i(比较的时候用num[i]获取)
(2)单调栈里面元素的顺序:求右边第一大时为从栈顶到栈底递增,右边第一小为递减
(3)具体情况:
- 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
- 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
- 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况
三、举例
求输入数组元素右边第一大的元素下标。 输入: [1,2,1] 输出: [1,-1,-1]
分析:
- 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况 --> 为了保持栈是递增顺序,把元素T[i]压入栈
- 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况 --> 因为求的是右边第一个大于的元素而非大于等于,所以也需要把元素T[i]压入栈
- 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况 --> 找到第一个大于的元素了,把栈内所有小于该元素的值全都弹出,并记录结果result[stack.top()] = i - stack.top()
class Solution { public int[] findFirstBig(int[] T) { int lens=T.length; int []res=new int[lens]; /** 如果当前遍历的元素 大于栈顶元素,表示 栈顶元素的 右边的最大的元素就是 当前遍历的元素, 所以弹出 栈顶元素,并记录 如果栈不空的话,还要考虑新的栈顶与当前元素的大小关系 否则的话,可以直接入栈。 注意,单调栈里 加入的元素是 下标。 */ Deque<Integer> stack=new LinkedList<>(); stack.push(0); for(int i=1;i<lens;i++){ if(T[i]<=T[stack.peek()]){ stack.push(i); }else{ while(!stack.isEmpty()&&T[i]>T[stack.peek()]){ res[stack.peek()]=i-stack.peek(); stack.pop(); } stack.push(i); } } return res; }
参考:代码随想录