题目与题解
739. 每日温度
题目链接:739. 每日温度
代码随想录题解:739. 每日温度
视频讲解:单调栈,你该了解的,这里都讲了!LeetCode:739.每日温度_哔哩哔哩_bilibili
解题思路:
最好想的就是暴力法,遍历数组中的每一个温度,并在此基础上,遍历当前元素后的每一个元素,直到找到比当前元素大的第一个元素,记录在结果中。但是这个方法超时了。
class Solution {public int[] dailyTemperatures(int[] temperatures) {int[] res = new int[temperatures.length];for (int i = 0; i < temperatures.length - 1; i++) {for (int j = i+1; j < temperatures.length; j++) {if (temperatures[j] > temperatures[i]) {res[i] = j - i;break;}}}return res;}
}
看完代码随想录之后的想法
单调栈,一种神奇的数据结构,一般针对一维数组使用。
它的基础逻辑是:栈内的元素存放顺序是单调的,其弹出元素也必然是一个有序的序列。为满足这一要求,以弹出序列为单调递增的序列为例,如果弹出的序列是单增的,那么栈底到栈顶的元素必然是单减的,此时压栈逻辑为:新元素比当前栈顶元素小,出栈逻辑为:新元素比当前栈顶元素要大,那不断弹出栈顶元素直到新元素比当前栈顶元素小或栈为空。
为了使用方便,单调栈一般存入的元素是其下标。
这道题用暴力法会直接超时,适合用单调栈这种空间换时间的方式,一次遍历就可以得到结果。设置单调栈s,先将第一个元素的下标0压入栈中,然后遍历剩下的元素。如果当前nums[i]小于等于栈顶下标对应的元素nums[s.peek()],则压栈;否则,计算栈顶下标和当前下标的差值i - s.peek(),即相差天数,存入结果数组中,然后弹出栈顶元素,重复操作直到栈空或栈顶元素大于nums[i]。
class Solution {public int[] dailyTemperatures(int[] temperatures) {int[] res = new int[temperatures.length];Stack<Integer> stack = new Stack<>();stack.push(0);for (int i = 1; i < temperatures.length; i++) {while (!stack.isEmpty() && temperatures[stack.peek()] < temperatures[i]) {res[stack.peek()] = i - stack.pop();}stack.push(i);}return res;}
}
遇到的困难
单调栈用起来还是不太熟练。
496.下一个更大元素 I
题目链接:496.下一个更大元素 I
代码随想录题解:496.下一个更大元素 I
视频讲解:单调栈,套上一个壳子就有点绕了| LeetCode:496.下一个更大元素_哔哩哔哩_bilibili
解题思路:
看答案。
看完代码随想录之后的想法
先理解题意:A B两个数组,先找到A数组中每一个元素在B数组中的所在位置,然后求从这个位置往后,找到比该元素大的第一个元素。
其实翻译过来跟第一题要求的东西是一样的,不同的是多了一个寻找下标的过程,以及求B数组单调栈时,其中可能存在A数组中不存在元素的情况,需要跳过。
由于两个数组中都没有重复元素,所以寻找下标的过程可以用哈希表来完成,用map来记录nums1的元素及其对应下标。设置单调栈用来计算过程,先将nums2数组的第一个下标0压入栈。由于可能不存在合适的元素,所以先初始化结果数组的元素都为-1.
遍历nums2数组的元素,与上一题类似,如果当前nums2[i]小于等于栈顶下标对应的元素nums2[s.peek()],则压栈;否则,先检查栈顶对应元素nums2[s.peek()]在nums1中是否存在,即map中是否存在key为nums2[s.peek()],如果不存在则直接弹出,存在则取出栈顶元素在nums1中对应的下标index = map.get(nums2[s.peek()]),然后更新结果数组res[index] = nums2[i],表示此时nums2[i]是nums1[index]对应的nums2中右边第一个比它大的数。
class Solution {public int[] nextGreaterElement(int[] nums1, int[] nums2) {HashMap<Integer, Integer> map = new HashMap<>();for (int i = 0; i < nums1.length; i++) {map.put(nums1[i], i);}int[] res = new int[nums1.length];Arrays.fill(res, -1);Stack<Integer> s = new Stack<>();s.add(0);for (int i = 1; i < nums2.length; i++) {while (!s.isEmpty() && nums2[i] > nums2[s.peek()]) {if (map.containsKey(nums2[s.peek()])) {int index = map.get(nums2[s.peek()]);res[index] = nums2[i];}s.pop();}s.push(i);}return res;}
}
遇到的困难
两个数组就绕了很多,理解题意理解了半天,思索如何在一个数组里面找对应另一个数组元素的位置也没想到用哈希,单调栈就更用不起来了。
还有单调栈由于保存的是数组的下标,而非数组元素,所以使用的时候也要注意,不要把下标当成元素使用。
今日收获
学习了一下单调栈的用法,很绕很妙。