单调栈
先介绍单调栈类型的题目,通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时就要想到可以用单调栈。
单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是只需要遍历一次。
分析单调栈的时候,我们需要考虑以下几点。
- 单调栈里存放的元素是什么?
单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取。
- 单调栈里元素是递增呢? 还是递减呢?
这里要根据具体的题目来分析。
使用单调栈主要有三个判断条件。
- 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
- 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
- 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况
把这三种情况分析清楚了,也就理解透彻了。
739. 每日温度
思路:借助单调栈来依次遍历数组,具体执行过程看图片分析。
遍历第一个
加入第二个数
加入第三个数
下一个状态
就是这样反复执行下去,直到遍历完所有的元素得出结果。
直接看代码。
class Solution {
public int[] dailyTemperatures(int[] temperatures) { // 利用单调栈辅助,一次遍历得出结果
int[] answer = new int[temperatures.length];
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
for (int i = 1; i < temperatures.length; i++) {
if (temperatures[i] < temperatures[stack.peek()]) {
stack.push(i);
} else {
while (!stack.isEmpty() && temperatures[stack.peek()] < temperatures[i]) {
answer[stack.peek()] = i - stack.peek();
stack.pop();
}
stack.push(i);
}
}
return answer;
}
}
496.下一个更大元素 I
思路:本题相对于上一题增加了条件,难度也有所增加。
这里我们还需要用到map集合,来快速找到nums2[i]是否在nums1中存在,我们好来更新结果。
遍历nums2,做单调栈处理,找到每一个元素右边最大元素,然后判断是否在nums1中存在,存在的话就要更新结果。
nums2的遍历过程与上一题相同。
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
//
int[] res = new int[nums1.length];
// 对结果数组初始化为-1
Arrays.fill(res, -1);
// map数组映射nums1,key对应值,val对应下标。
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
map.put(nums1[i], i);
}
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
for (int i = 1; i < nums2.length; i++) {
if (nums2[i] < nums2[stack.peek()]) {
stack.push(i);
} else {
while (!stack.isEmpty() && nums2[stack.peek()] < nums2[i]) {
if (map.get(nums2[stack.peek()]) != null) { // 该数在nums1中存在,需要更新结果。
res[map.get(nums2[stack.peek()])] = nums2[i];
}
stack.pop();
}
stack.push(i);
}
}
return res;
}
}