单调栈系列
单调栈实际上就是栈,只是利用了一些巧妙的逻辑,使得每次新元素入栈后,栈内的元素都保持有序(单调递增或单调递减)。
题目列表
1、496 Next Great Element
2、739 Daily Temperature
3、503 Next Greater Element II
496 Next Great Element
题目描述
这道题如果暴力解法的话很容易想到,直接遍历该数字后面的数,然后返回值即可。时间复杂度O(n1);
可以换一个方式思考,这里我们先上代码,方便解释;
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
Map<Integer,Integer> map =new HashMap<>();
int n2 =nums2.length;
Stack<Integer> s = new Stack<Integer>();
for (int i = n2-1; i >= 0; i--) {
while(!s.isEmpty() && s.peek()<=nums2[i]){
s.pop();
}
map.put(nums2[i],s.isEmpty()? -1: s.peek());
s.add(nums2[i]);
}
int n1 = nums1.length;
int[] ans =new int[n1];
for (int i = 0; i < n1; i++) {
ans[i] = map.get(nums1[i]);
}
return ans;
}
我们先求出nums2中每个数的next great element,然后存HashMap中,再遍历nums1在HashMap找到所求结果。
关键在于nums2中如何求得每一个数的next great element呢?
这里我们先创建栈,然后在栈中排出比当前nums2[i]小的值,如果栈S不为空,得到的s.peek()就是nums2[i]的next great element了。最后我们将nums2[i]添加进栈,就完成了单调栈的整个过程。
注意点:我们需要从后面向前遍历,这样我们才能够得到next great element,如果是从前向后遍历的话,得到就是 previous great number了。(想一想是不是这个道理)
虽然是for循环嵌套while,但是这个算法的时间复杂度为O(n);因为每个元素进栈一次,并且最多也只会被pop一次,所以时间复杂度为O(n)。
739 Daily Temperature
题目描述
这道题求的是隔了几天才会有更高的温度,我们只需要将元素的下标进栈即可。
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] ans = new int[n];
Stack<Integer> s = new Stack<>();
for (int i = n - 1; i >= 0; i--) {
while (!s.isEmpty() && temperatures[s.peek()] <= temperatures[i]) {
s.pop();
}
ans[i] = s.isEmpty()? 0:s.peek()-i;
s.add(i);
}
return ans;
}
503 Next Greater Element II
注意到这里数组变成了环形数组,解决这一类问题的套路就是将数组的长度翻倍;
实际操作中也并不需要翻倍数组,而是将下标翻倍即可
public int[] nextGreaterElements(int[] nums) {
int n = nums.length;
int n2 = 2*n;
int[] ans = new int[n];
Stack<Integer> s = new Stack<Integer>();
for (int i = n2-1; i >= 0; i--) {
while(!s.isEmpty() && s.peek()<=nums[i%n]){
s.pop();
}
if(i<=n-1){
ans[i] = s.isEmpty()? -1:s.peek();
}
s.add(nums[i%n]);
}
return ans;
}