代码随想录Day63 |503.下一个更大元素II 42. 接雨水
- 503.下一个更大元素II
- 42.接雨水
- 双指针
- 单调栈
503.下一个更大元素II
文档讲解:代码随想录
视频讲解: 单调栈,成环了可怎么办?LeetCode:503.下一个更大元素II
状态
单调栈中存储的元素和单调性都和之前一样
主要是对循环数组怎么处理
//循环数组的处理方法
//循环数组相当于是需要遍历两次原本的数组
//1. 可以再复制一个数组在原本的数组后面
//2. 将遍历的循环长度增加为2*n-1,然后对i取mod(n)那么超过n的i也会变为i
class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {int len = nums.size();vector<int> res(len,-1);if(len == 0) return res;stack<int> check;check.push(0);for(int i = 1;i<2*len-1;i++){while(!check.empty() && nums[i%len] > nums[check.top()]){res[check.top()] = nums[i%len];check.pop();}check.push(i%len);}return res;}
};
42.接雨水
文档讲解:代码随想录
视频讲解: 单调栈,经典来袭!LeetCode:42.接雨水
状态
双指针
两个指针分别从头和尾向中间移动,并记录扫描过的左端和右端木板最大值。
当右端木板最大值比左端木板最大值大时,我们考虑左指针指向的当前木板。那么其一定是可以存水的,因为其右边有比他高的木板。具体存水量是当前的左端最大值减去当前木板高度。
//双指针
class Solution {
public:int trap(vector<int>& height) {int left = 0;int right = height.size()-1;int res = 0;int leftmax = height[left];int rightmax = height[right];while(left <= right){leftmax = max(leftmax,height[left]);rightmax = max(rightmax,height[right]);//当左边的最高小于右边最高//可以以左边木板的高度来确定盛水量,因为右边始终有一个比他高的为他兜底//有点贪心的想法//盛水量就是左边的最大值减去当前木板的高度。if(leftmax<rightmax){res += leftmax-height[left];left++;}else{res += rightmax-height[right];right--;}}return res;}
};
单调栈
对于一个下标i寻找其左边的第一个大值和右边第一个大值,这个位置的积水量就可以求得
对于栈内一个可以积水的情况,栈头元素表示当前木板,栈头第二个元素应当表示当前木板的左边最大值,待入栈元素表示当前木板的右边木板。所以在该单调栈中应该是栈头元素较小,栈底元素较大。
当遇到与栈头相同的元素要入栈时,应当弹出栈头,压入最新的下标。
栈中存放的元素:当前木板的下标。
class Solution {
public:int trap(vector<int>& height) {int res = 0;stack<int> check;check.push(0);for(int i = 1;i<height.size();i++){//如果待压入元素比栈头元素小直接压入if(height[i] < height[check.top()]){check.push(i);}//如果相等,先弹出再压入else if(height[i] == height[check.top()]){check.pop();check.push(i);}//如果大,那说明可以计算积水量else{while(!check.empty() && height[i] > height[check.top()]){//当前积水的木板int mid = check.top();check.pop();if(!check.empty()){//计算积水高度,应当是栈头第二个元素和待压入元素的最小值int h = min(height[check.top()],height[i]) - height[mid];//计算积水宽度int w = i-check.top()-1;res += h*w;}}//压入check.push(i);}}return res;}
};