什么是单调栈?
就是栈内元素单调递增或单调递减的栈!
单调栈一般用作求解 Next Greater Element 问题:寻找下一个更大(更小)的元素。
假设一个数组 [ 3, 7, 5, 11, 4, 8, 6],我们想要找到这个数组每个元素后面第一个更大元素,
一般我们直接按顺序进行遍历的暴力解法的时间复杂度是O(n^2)。
但是,如果我们使用一个栈来操作:
- 将第一个数组元素入栈;
- 将后一个数组元素与栈顶元素比较,如果小于栈顶元素则入栈,如果大于栈顶元素则将栈顶元素出栈;
- 依次遍历所有数组元素,最后还在栈中的元素,表示其后没有更大元素。
时间复杂度为O(n)。
练习题
本文所有练习题均Ctrl+C引自力扣(leetcode)。
1.下一个更大元素
题目:
给定两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
示例:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
nums1 中第一个元素 4 在 nums2 中出现在第三个元素位置,其右没有更大元素, 返回 -1;
nums1 中第二个元素 1 在 nums2 中出现在第一个元素位置,其右第一个更大元素为3, 返回 3;
nums1 中第三个元素 2 在 nums2 中出现在最后位置,其右没有更大元素, 返回 -1;
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
思路:
- 暴力解法:
使用两个下标和一个用来记录结果的数组,向右遍历第一个数组每个元素,先在第二个数组中找到与第一数组元素(nums1[Index])相等的那个元素(nums2[hignerIndex]),在继续向右遍历直到找到一个比第一数组对应元素更大的元素(nums1[Index] < nums2[higherIndex]),如果找到就将该元素存入结果数组,如果没有找到就存入-1。
int[] ans = new int[]; // 结果数组
for ( int Index =0; Index < nums1.Length; Index++ ){
int higherIndex = 0; // 第二个数组的下标
// 遍历第二个数组,寻找相等元素
for ( int i = 0; i < nums2.Length; i++ ){
if ( nums1[Index] = nums2[i] ){
higherIndex = i;
break;
}
}
// 继续遍历第二个数组,直到超出索引或者找到更大的元素
while ( higherIndex < nums2.Length && nums2[higherIndex] <= nums1[Index] ){
higherIndex++;
}
if ( higherIndex < nums2.Length ){
// 找到更大的元素,对应元素存入结果数组
ans[Index] = nums2[higherIndex];
}else{
// 没有找到更大的元素,结果数组存入-1
ans[Index] = -1;
}
}
- 单调栈:
先不管第一个数组 nums1 , 直接对第二个数组 nums2 中的元素操作,找出每个元素后面的更大的元素,将它们存入哈希表中,之后再遍历 nums1 ,从哈希表中找出答案。
题解(python):
class Solution: