单调栈里面是递增或者递减的
739.每日温度
单调栈:适合求当前元素左面或者右面第一个比当前元素大或小的元素
单调栈的作用就是记录遍历过的元素,和当前遍历到的元素做对比
今天正式开始单调栈,这是单调栈一篇扫盲题目,也是经典题。
大家可以读题,思考暴力的解法,然后在看单调栈的解法。 就能感受出单调栈的巧妙
相当于输出下标距离
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
//栈里面需要存的是数组的下标!!
//栈头是新的元素栈内是旧的,但都是遍历过的放到栈里
//如果当前遍历的元素比栈内元素小 说明没找到大于栈头的下一个最大的元素 于是当前便利的元素入栈
Deque<Integer> stack=new LinkedList<>();
int[] res=new int[temperatures.length];
stack.push(0);
for(int i=0;i<temperatures.length;i++){
//当前遍历的小于栈头
if(temperatures[i]<=temperatures[stack.peek()]){
stack.push(i);
}else{
while(!stack.isEmpty()&&temperatures[i]>temperatures[stack.peek()]){
res[stack.peek()]=i-stack.peek();
stack.pop();
}
stack.push(i);
}
}
return res;
}
}
思路整理:**通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。**时间复杂度为O(n)。
在这道题中,主要是寻找当前遍历到的元素第一个比它还要大的元素,所以为记录遍历过的元素,每次遍历都会放到单调栈中,如果每一次比上一次还要小就没有元素弹出,于是在栈中形成单调递增的形式。如果当前元素大于队头元素则让队头元素不断弹出。整体遍历结束则算法结束,留在队列里面的说明他们后面没在出现比他们还大的元素,所以结果集中对应位置为0.
496.下一个更大元素 I
本题和 739. 每日温度 看似差不多,其实 有加了点难度。
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int[] res=new int[nums1.length];
//初始化默认都找不到
for(int i=0;i<nums1.length;i++){
res[i]=-1;
}
Deque<Integer> stack=new LinkedList<>();
//思路:
//要在数组二里面找数组二中右边大的元素(于是单调栈里面是单调递减),于是遍历数组2
//当前遍历的元素是栈头的下一个元素
//另外在遍历数组的过程中需要找到值对应在数组1中的位置 所以考虑用map做kv映射,将数组1变成map
//根据数组1创建map,因为哈希表用key找value很方便,此题是用num2的值去找num1的下标(值找下标),所以map的key应该是值,value应该是下标(题中说了数组没有重复元素)
HashMap<Integer,Integer> hashMap= new HashMap<>();
for(int i=0;i<nums1.length;i++){
hashMap.put(nums1[i],i);
}
//栈中初始装入nums2下标0
stack.push(0);
for(int i=1;i<nums2.length;i++){
//先正常遍历nums2,得出nums2中当前值的下一个最大值,如果当前值是nums1中的则把结果记录在结果集
if(nums2[i]<=nums2[stack.peek()]){
stack.push(i);
}else{
while(!stack.isEmpty()&&nums2[i]>nums2[stack.peek()]){
if(hashMap.containsKey(nums2[stack.peek()])){
Integer index=hashMap.get(nums2[stack.peek()]);
res[index]=nums2[i];
}
stack.pop();
}
stack.push(i);
}
}
return res;
}
}
思路:
输出:一个nums1长度的数组,元素是每个对应nums1元素由nums2得出来的nums2中的最大值
输入:nums1,nums2数组
需定义的:
res数组
栈(每次通过与队头比较,来找右边最大值)
hashMap(如果确定了队头的最大值,则需查看队(装数组2的下标)头对应的nums2值在不在nums1中,如果在当前所确定的最大值就是要放在结果集里面的最大值)