坪山网站建设特色,设计公司logo的网站,零基础网站建设教学服务,wordpress多站点好用吗503.下一个更大元素II
思路
做本题之前建议先做739. 每日温度 (opens new window)和 496.下一个更大元素 I (opens new window)。
这道题和739. 每日温度 (opens new window)也几乎如出一辙。
不过#xff0c;本题要循环数组了。
关于单调栈的讲解我在题解739. 每日温度 …503.下一个更大元素II
思路
做本题之前建议先做739. 每日温度 (opens new window)和 496.下一个更大元素 I (opens new window)。
这道题和739. 每日温度 (opens new window)也几乎如出一辙。
不过本题要循环数组了。
关于单调栈的讲解我在题解739. 每日温度 (opens new window)中已经详细讲解了。
本篇侧重与说一说如何处理循环数组。
相信不少同学看到这道题就想直接把两个数组拼接在一起然后使用单调栈求下一个最大值不就行了
确实可以
将两个nums数组拼接在一起使用单调栈计算出每一个元素的下一个最大值最后再把结果集即result数组resize到原数组大小就可以了。
代码如下
class Solution {public int[] nextGreaterElements(int[] nums) {int len nums.length;StackInteger st new Stack();int[] res new int[len];Arrays.fill(res, -1);st.push(0);for (int i 1; i len * 2; i) {if (nums[i % len] nums[st.peek() % len]) {while (!st.isEmpty() nums[i % len] nums[st.peek()]) {//当前元素大于 栈顶元素//弹出栈顶元素res[st.pop()] nums[i % len];}}//当前元素小于等于 栈顶元素 放入栈中//无论当前元素小于等于还是大于都将当前元素放入栈中st.push(i%len);}return res;}
} 42. 接雨水
思路
单调栈解法
关于单调栈的理论基础单调栈适合解决什么问题单调栈的工作过程大家可以先看这题讲解 739. 每日温度 (opens new window)。
单调栈就是保持栈内元素有序。和栈与队列单调队列 (opens new window)一样需要我们自己维持顺序没有现成的容器可以用。
通常是一维数组要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置此时我们就要想到可以用单调栈了。
而接雨水这道题目我们正需要寻找一个元素右边最大元素以及左边最大元素来计算雨水面积。
#准备工作
那么本题使用单调栈有如下几个问题
首先单调栈是按照行方向来计算雨水如图 知道这一点后面的就可以理解了。
使用单调栈内元素的顺序
从大到小还是从小到大呢
从栈头元素从栈头弹出到栈底的顺序应该是从小到大的顺序。
因为一旦发现添加的柱子高度大于栈头元素了此时就出现凹槽了栈头元素就是凹槽底部的柱子栈头第二个元素就是凹槽左边的柱子而添加的元素就是凹槽右边的柱子。
如图 关于单调栈的顺序给大家一个总结 739. 每日温度 (opens new window)中求一个元素右边第一个更大元素单调栈就是递增的84.柱状图中最大的矩形 (opens new window)求一个元素右边第一个更小元素单调栈就是递减的。
遇到相同高度的柱子怎么办。
遇到相同的元素更新栈内下标就是将栈里元素旧下标弹出将新元素新下标加入栈中。
例如 5 5 1 3 这种情况。如果添加第二个5的时候就应该将第一个5的下标弹出把第二个5添加到栈中。
因为我们要求宽度的时候 如果遇到相同高度的柱子需要使用最右边的柱子来计算宽度。
如图所示 栈里要保存什么数值
使用单调栈也是通过 长 * 宽 来计算雨水面积的。
长就是通过柱子的高度来计算宽是通过柱子之间的下标来计算
那么栈里有没有必要存一个pairint, int类型的元素保存柱子的高度和下标呢。
其实不用栈里就存放下标就行想要知道对应的高度通过height[stack.top()] 就知道弹出的下标对应的高度了。
所以栈的定义如下
stackint st; // 存着下标计算的时候用下标对应的柱子高度明确了如上几点我们再来看处理逻辑。
#单调栈处理逻辑
以下操作过程其实和 739. 每日温度 (opens new window)也是一样的建议先做 739. 每日温度 (opens new window)。
以下逻辑主要就是三种情况
情况一当前遍历的元素柱子高度小于栈顶元素的高度 height[i] height[st.top()]情况二当前遍历的元素柱子高度等于栈顶元素的高度 height[i] height[st.top()]情况三当前遍历的元素柱子高度大于栈顶元素的高度 height[i] height[st.top()]
先将下标0的柱子加入到栈中st.push(0);。 栈中存放我们遍历过的元素所以先将下标0加进来。
然后开始从下标1开始遍历所有的柱子for (int i 1; i height.size(); i)。
如果当前遍历的元素柱子高度小于栈顶元素的高度就把这个元素加入栈中因为栈里本来就要保持从小到大的顺序从栈头到栈底。
代码如下
if (height[i] height[st.top()]) st.push(i);如果当前遍历的元素柱子高度等于栈顶元素的高度要跟更新栈顶元素因为遇到相相同高度的柱子需要使用最右边的柱子来计算宽度。
代码如下
if (height[i] height[st.top()]) { // 例如 5 5 1 7 这种情况st.pop();st.push(i);
}如果当前遍历的元素柱子高度大于栈顶元素的高度此时就出现凹槽了如图所示 取栈顶元素将栈顶元素弹出这个就是凹槽的底部也就是中间位置下标记为mid对应的高度为height[mid]就是图中的高度1。
此时的栈顶元素st.top()就是凹槽的左边位置下标为st.top()对应的高度为height[st.top()]就是图中的高度2。
当前遍历的元素i就是凹槽右边的位置下标为i对应的高度为height[i]就是图中的高度3。
此时大家应该可以发现其实就是栈顶和栈顶的下一个元素以及要入栈的元素三个元素来接水
那么雨水高度是 min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度代码为int h min(height[st.top()], height[i]) - height[mid];
雨水的宽度是 凹槽右边的下标 - 凹槽左边的下标 - 1因为只求中间宽度代码为int w i - st.top() - 1 ;
当前凹槽雨水的体积就是h * w。
求当前凹槽雨水的体积代码如下
while (!st.empty() height[i] height[st.top()]) { // 注意这里是while持续跟新栈顶元素int mid st.top();st.pop();if (!st.empty()) {int h min(height[st.top()], height[i]) - height[mid];int w i - st.top() - 1; // 注意减一只求中间宽度sum h * w;}
}关键部分讲完了整体代码如下