数据结构与算法:单调栈的使用

单调栈的初次使用

输入:
 nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: 
[-1,3,-1]
解释:
    对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
    对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
    对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。

之前有遇到过类似这样的问题,都是关于求数组更大元素的问题,当时并不太清楚单调栈的使用,而是通过暴力解法对数组疯狂遍历,最后才得到数组每个位置对应更大元素位置
对于此类问题,用单调栈的思路去解决是比较容易的。
在这个题的思路,尽量在对nums2数组一次遍历后能够得到一个result集合(将每个位置对应的更大元素得到),对于每个当前元素应该关注它的右边元素。每次将小的元素压入栈中,出现更大的元素则是栈顶元素对应的更大值。
单调栈的细节:小的应该被pop,大的还要push进栈中,这样可以保持栈的单调性。
具体操作:我们首先把第一个元素 nums2[1] 放入栈,随后对于第二个元素 nums2[2],如果 nums2[2] > nums2[1],那么我们就找到了 nums2[1] 的下一个更大元素 nums2[2],此时就可以把 nums2[1] 出栈并把 nums2[2] 入栈;如果 nums2[2] <= nums2[1],我们就仅把 nums2[2] 入栈。对于第三个元素 nums2[3],此时栈中有若干个元素,那么所有比 nums2[3] 小的元素都找到了下一个更大元素(即 nums2[3]),因此可以出栈,在这之后,我们将 nums2[3] 入栈,以此类推。
代码实现

    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
    	Map<Integer, Integer> reuslt = new HashMap<Integer, Integer>();
    	Stack<Integer> stacks = new Stack<>();
    	for(int i = 0;i < nums2.length ; i++) {
    		while(!stacks.empty() && nums2[i] > stacks.peek()) {
    			reuslt.put(stacks.pop(),nums2[i]);
    		}
    		stacks.push(nums2[i]);
    	}
    	while(!stacks.empty()) {
    		reuslt.put(stacks.pop(), -1);
    	}
    	for(int i = 0 ; i < nums1.length;i++ ) {
    		nums1[i] = reuslt.get(nums1[i]);
    	}
    	return nums1;
    }

时间复杂度:O(M+N),其中 M 和 N分别是数组 nums1 和 nums2 的长度。
空间复杂度:O(N)。我们在遍历 nums2 时,需要使用栈,以及哈希映射用来临时存储答案。
这个题最优解肯定并不是使用单调栈的方式实现,但是关於单调栈的思想是比较适合解决对这类问题的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章