1.下一个更大元素II 题503
循环数组有两种方法,一是用同一个数组拼接成两个数组,实现假循环;二是遍历两遍,用求余的方法。求余的方法更简便。
class Solution {
public:vector nextGreaterElements(vector& nums) {int n = nums.size();vector result(n,-1); //初始化结果集,开始全不存在,赋-1stack st; //递增栈for(int i = 0;i < n*2;i++){ while(!st.empty() && nums[i % n] > nums[st.top()]){ //情况三result[st.top()] = nums[i % n];st.pop();}st.push(i % n); //情况一和二}return result;}
};
2.接雨水 题42
两种方法,双指针法和单调栈的方法。
①双指针
按照列去计算
雨水的面积 = min(左侧柱子最高高度-右侧柱子最高高度) - 当前柱子的高度
class Solution {
public:int trap(vector& height) {int sum = 0;for (int i = 0; i < height.size(); i++) {// 第一个柱子和最后一个柱子不接雨水if (i == 0 || i == height.size() - 1) continue;int rHeight = height[i]; // 记录右边柱子的最高高度int lHeight = height[i]; // 记录左边柱子的最高高度for (int r = i + 1; r < height.size(); r++) {if (height[r] > rHeight) rHeight = height[r];}for (int l = i - 1; l >= 0; l--) {if (height[l] > lHeight) lHeight = height[l];}int h = min(lHeight, rHeight) - height[i];if (h > 0) sum += h;}return sum;}
};
但这种方法在LeetCode上超出时机限制
②单调栈
用行的方法计算
从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。
因为一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。
遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中
取栈顶元素,将栈顶元素弹出,这个就是凹槽的底部,也就是中间位置,下标记为mid,对应的高度为height[mid](就是图中的高度1)。
此时的栈顶元素st.top(),就是凹槽的左边位置,下标为st.top(),对应的高度为height[st.top()](就是图中的高度2)。
当前遍历的元素i,就是凹槽右边的位置,下标为i,对应的高度为height[i](就是图中的高度3)。
大概理解了,二刷再详细看。
详细在
https://programmercarl.com/0042.%E6%8E%A5%E9%9B%A8%E6%B0%B4.html
class Solution {
public:int trap(vector& height) {if (height.size() <= 2) return 0; // 可以不加stack st; // 存着下标,计算的时候用下标对应的柱子高度st.push(0);int sum = 0;for (int i = 1; i < height.size(); i++) {if (height[i] < height[st.top()]) { // 情况一st.push(i);} if (height[i] == height[st.top()]) { // 情况二st.pop(); // 其实这一句可以不加,效果是一样的,但处理相同的情况的思路却变了。st.push(i);} else { // 情况三while (!st.empty() && height[i] > height[st.top()]) { // 注意这里是whileint 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;}}st.push(i);}}return sum;}
};