本文将介绍使用单调栈解决两个问题:503.下一个更大元素II 和 42. 接雨水。单调栈是一种常用的数据结构,用于解决求解下一个更大元素和接雨水问题。
503.下一个更大元素II
题目描述:
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字x的下一个更大的元素是指数组中比x大的第一个元素,这个元素存在于数组中的某个位置,如果不存在,则输出-1。
示例: 输入: [1,2,1] 输出: [2,-1,2]
解题思路:
首先,我们需要将输入的循环数组复制一遍,这样我们就可以通过单调栈找到每个元素的下一个更大元素。然后我们可以使用单调栈来处理该问题,具体步骤如下:
-
创建一个栈,用于存储数组元素的下标。
-
遍历数组,将每个元素的下标压入栈中。
-
如果当前元素比栈顶元素大,则说明栈顶元素的下一个更大元素就是当前元素。我们可以将栈顶元素弹出,并将当前元素的下标存储在栈顶元素的位置上。
-
最后,栈中剩余的元素表示该元素后面没有比它更大的元素,我们可以将它们的值设置为-1。
-
最后,我们只需要返回新数组的前n个元素即可,其中n是原数组的长度。
代码如下:
class Solution {
public int[] nextGreaterElements(int[] nums) {
int n = nums.length;
int[] res = new int[n];
Arrays.fill(res, -1);
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n * 2; i++) {
int num = nums[i % n];
while (!stack.isEmpty() && num > nums[stack.peek()]) {
res[stack.pop()] = num;
}
if (i < n) stack.push(i);
}
return res;
}
}
时间复杂度:O(n)。
空间复杂度:O(n)。
- 接雨水
题目描述:
给定n个非负整数表示每个宽度为1的柱子的高度图,计算下雨后它能够捕获的雨水量。
示例: 输入: [0,1,0,2,1,0,1,3,2,1,2,1] 输出: 6
解题思路:
对于每个位置,能够接到的雨水数量取决于左侧最高的柱子和右侧最高的柱子中较小的一个。我们可以使用单调栈来找到左侧最高的柱子和右侧最高的柱子。
具体步骤如下:
-
创建一个栈,用于存储每个柱子的下标。
-
从左到右遍历所有柱子,如果当前柱子的高度大于栈顶柱子的高度,则说明栈顶柱子无法继续接到雨水了,可以将其弹出。我们可以将当前柱子的下标压入栈中。
-
如果当前柱子的高度小于等于栈顶柱子的高度,则说明当前柱子可以继续接到雨水。我们可以将当前柱子的下标压入栈中。
-
遍历完所有柱子后,栈中剩余的元素表示该元素右侧没有比它更高的柱子,因此没有办法接到雨水。
-
从左到右遍历所有柱子,对于每个柱子,我们可以找到左侧最高的柱子和右侧最高的柱子,然后计算当前位置能够接到的雨水数量。
代码如下:
class Solution {
public int trap(int[] height) {
int n = height.length;
int res = 0;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
int cur = stack.pop();
if (stack.isEmpty()) break;
int left = stack.peek();
int h = Math.min(height[left], height[i]) - height[cur];
res += h * (i - left - 1);
}
stack.push(i);
}
return res;
}
}
时间复杂度:O(n)。
空间复杂度:O(n)。