单调栈
怎么能想到用单调栈呢?
通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时就要想到可以用单调栈了
单调栈的原理是什么呢?
单调栈的本质
单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是只需要遍历一次
单词栈里面存什么
单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取
单调栈中元素是递增还是递减呢
顺序为 从栈头到栈底的顺序
739. 每日温度
题目链接:力扣
思路
首先想到的就是暴力解法,但是会超时
这道题目就是找到右边一个元素比自己大,所以要使用递增循序,因为只有递增的时候,加入一个元素i,才知道栈顶元素在数组中右面第一个比栈顶元素大的元素是i
单调栈的三种情况:
当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
直接添加进去,符合从栈顶到栈底是递增的
当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
直接添加进去,因为题目要求的是大于的,不是大于等于的,而且也是符合从栈顶到栈底是递增的
当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况
此时,就可以记录栈顶元素的结果了(右边第一个比之大的数字)
记录结果,弹出下标,添加新下标
每日温度
class Solution { public int[] dailyTemperatures(int[] temperatures) { int lens = temperatures.length; // 创建结果数组 int[] result = new int[lens]; // 创建栈 Deque<Integer> stack = new LinkedList<>(); stack.push(0); // 获取结果 for (int i = 1; i < lens; i++) { // 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况 // 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况 if ( temperatures[i] <= temperatures[stack.peek()]) { stack.push(i); } else { // 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况 while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) { result[stack.peek()] = i - stack.peek(); stack.pop(); } stack.push(i); } } return result; } }
496.下一个更大元素 I
题目链接:力扣
思路
这道题比较简单,模拟的做法就可以做出来
如果说模拟法是一种正向的思路,那么单调法就是逆向的思路
模拟法:遍历nums1,在nums2中找到nums1[i] 元素的位置,然后通过这个位置向后遍历nums2,第一个大于的就是我们要找的结果
单调栈:遍历nums2,算出每一个元素的右边第一大数字,然后查看nums1 中有没有这个元素,有的话,就可以将这个结果收起来
模拟法就是,算出自己需要的
单调栈就是,我都算,你要你取结果
下一个更大元素
模拟法
class Solution { public int[] nextGreaterElement(int[] nums1, int[] nums2) { // 创建结果数组 int[] result = new int[nums1.length]; // 初始化数组 Arrays.fill(result,-1); for (int i = 0; i < nums1.length; i++) { // 找到当前数对应在nums的位置 int index = 0; for (int j = 0; j < nums2.length; j++) { if (nums1[i] == nums2[j]) { index = j + 1; break; } } for (int k = index; k < nums2.length; k++) { // 找出右侧第一个大于的数 if (nums2[k] > nums1[i]) { result[i] = nums2[k]; break; } } } return result; } }
单调栈
class Solution { public int[] nextGreaterElement(int[] nums1, int[] nums2) { // 创建栈 Stack<Integer> stack = new Stack<>(); // 结果数组 int[] result = new int[nums1.length]; // 初始化数组 Arrays.fill(result,-1); // 映射数组 HashMap<Integer,Integer> hashMap = new HashMap<>(); for (int i = 0; i < nums1.length; i++) { hashMap.put(nums1[i],i); } // 初始化单调栈 stack.add(0); // 推导结果 for (int i = 1; i < nums2.length; i++) { if (nums2[i] <= nums2[stack.peek()]) { stack.add(i); } else { while (!stack.isEmpty() && nums2[i] > nums2[stack.peek()]) { if (hashMap.containsKey(nums2[stack.peek()])) { Integer index = hashMap.get(nums2[stack.peek()]); result[index] = nums2[i]; } stack.pop(); } stack.add(i); } } return result; } }