代码随想录Day63 |503.下一个更大元素II 42. 接雨水

代码随想录Day63 |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;
    }
};
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值