代码随想录算法训练营第五十九天|503.下一个更大元素II、42. 接雨水

105 阅读1分钟

503.下一个更大元素II

题目链接:503.下一个更大元素II

思路:本题仍然是利用单调栈来寻找下一个更大数值的问题,只不过数组可以循环来寻找。我的解决方法是,将两个相同的数组拼接,然后利用单调栈来寻找就好了(寻找过程与昨天的每日温度类似)。

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] res = new int[nums.length];
        Arrays.fill(res, -1);
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        int[] nums2 = new int[nums.length + nums.length];
        for (int i = 0; i < nums.length; i++) {
            nums2[i] = nums[i];
            nums2[i + nums.length] = nums[i];
        }
        for (int i = 1; i < nums2.length; i++) {
            if (nums2[i] <= nums2[stack.peek()]) {
                stack.push(i);
            } else {
                while (!stack.isEmpty() && nums2[stack.peek()] < nums2[i]) {
                    if (stack.peek() < nums.length) {
                        res[stack.peek()] = nums2[i];
                    } else {
                        res[stack.peek() - nums.length] = nums2[i];
                    }
                    stack.pop();
                }
                stack.push(i);
            }
        }
        return res;
    }
}

42. 接雨水

题目链接:42. 接雨水

思路:本题十分经典。可以使用动态规划、双指针法、单调栈来解决,目前只介绍单调栈方法,二刷补充其他方法。

使用单调栈需要理解的几个问题:

  1. 单调栈是按照行的方向来存储雨水的

image.png

  1. 单调栈中元素的顺序应该是什么样的。

从栈底到栈头应该是从大到小的顺序。因为一旦发现更大的元素,说明我们就要接雨水(更新结果)了

  1. 遇到相同高度的柱子怎么办

遇到相同高度的柱子应当更新栈顶的元素,将其更新为最新的,用最右边的柱子来进行计算。

  1. 栈里应该保存什么值

这里栈中只需要保存数组的下标就好了。

class Solution {
    public int trap(int[] height) { // 找每个柱子两边第一个大于该柱子高度的柱子
        int res = 0;
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        for (int i = 1; i < height.length; i++) {
            if (height[i] < height[stack.peek()]) {
                stack.push(i);
            } else if (height[i] == height[stack.peek()]) {
                stack.pop();
                stack.push(i);
            } else {
                while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
                    int mid = stack.pop();
                    if (!stack.isEmpty()) {
                        int left = stack.peek();
                        int h = Math.min(height[left], height[i]) - height[mid];
                        int w = i - left - 1;
                        res += (h * w);

                    }
                }
                stack.push(i);
            }
        }
        return res;
    }
}