单调栈总结
它的定义就是每次新的元素入栈都能保证栈是一个单调递增或递减的结构。因此需要通过一些逻辑操作来保证这个结构。
结合题目来看:
使用单调栈来解决next greater number(下一个更大元素)的问题,leetcode496:给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。(原文链接:leetcode-cn.com/problems/ne…)
例:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
题目所表达的意思就是对于nums2中的每个元素找到下一个比它更大的数,可以看图分析这个题目,把数组中的每个元素看成是一个人,对应元素的值就是这个人的身高,从当前元素往后看,看到的比自己高的那一个元素就是当前元素的next greater number了。怎么保证当前元素往后看能看到比自己大的元素呢?那就是使用单调栈,首先使用一个栈去存储元素这个栈是一个单调递增的栈,栈顶元素是当前栈中的最小元素。从数组末尾开始往前遍历:
1、如果当前入栈的元素比栈顶元素小就说明当前元素的ngn就是栈顶元素;
2、反之为了将这个元素入栈同时保证单调栈的结构就必须不断出栈直到栈顶元素大于当前元素或者空栈为止,(栈空就说明了当前元素没有ngn)。
这样就可以求得每一个元素的ngn。
代码:
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
//使用Deque来创建stack,而不要使用Stack类(它是继承Vector的效率低)
Deque<Integer> stack = new LinkedList<>();
//使用哈希表存储,最后要遍历nums1中的元素的
Map<Integer,Integer> hashmap = new HashMap<Integer,Integer>();
for (int i=nums2.length-1; i>=0; i--){
//如果栈不为空且当前元素大于栈顶元素就一直出栈保证单调栈结构
while(!stack.isEmpty() && nums2[i]>stack.peek()){
stack.pop();
}
//如果栈空说明当前元素没有ngn,否则直接返回栈顶元素
hashmap.put(nums2[i],stack.isEmpty()?-1:stack.peek());
//然后把当前元素入栈
stack.push(nums2[i]);
}
int lens1 = nums1.length;
int[] res = new int[lens1];
for (int i=0; i<lens1; i++){
res[i] = hashmap.get(nums1[i]);
}
return res;
}
labuladong算法小抄里面解释while循环的作用:把两个高个元素之间的元素排除,它们的存在没有意义,因为前面挡着更高的元素,所以它们不可能被作为后续进来的元素的ngn了。