數據結構與算法:單調棧的使用

單調棧的初次使用

輸入:
 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 時,需要使用棧,以及哈希映射用來臨時存儲答案。
這個題最優解肯定並不是使用單調棧的方式實現,但是關於單調棧的思想是比較適合解決對這類問題的

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