当青训营遇上码上掘金 主题4 攒青豆

1,063 阅读1分钟

当青训营遇上码上掘金

主题4 攒青豆

image.png

第一眼看到这个题目,我就立马想到了以前在力扣上面刷到的一道题目,接雨水:

image.png

只不过力扣是雨水,这里是青豆

还是个困难的tag

前置知识

单调栈:

image.png

找出每个数字左边第一个小于自己的数字,没有的话返回-1

题目中会有两个性质:

1.如果height[i]>height[j] 并且 i<j 的话,height[i]肯定不会是正确答案

2.如果height[i]<height[j] 并且i<j的话,此次遍历的值可能是height[i]和height[j]中间或者两边,三种情况

其实先可以理解成,每遍历一个元素的时候,就从栈里找到最小的,然后将元素添加到栈顶...

有了上面的两个性质就可以这么做:

  1. 开辟一个栈
  2. 从栈顶开始遍历,直到把所有大于等于此次的遍历的数字的时候停止
  3. 如果栈空了,返回-1,不空的话返回栈顶
  4. 将此次遍历的值添加到栈顶
#include <iostream>

using namespace std;

const int N = 100010;

int stk[N], tt;

int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        int x;
        scanf("%d", &x);
        while (tt && stk[tt] >= x) 
            tt -- ;
        if (!tt) printf("-1 ");
        else printf("%d ", stk[tt]);
        stk[ ++ tt] = x;
    }

    return 0;
}

本题思路

举个例子:

image.png

1.首先前三个柱子入栈,不能形成凹槽,不能存青豆

image.png

2.第四根柱子就可以存青豆了,需要加上可以存储的部分

image.png

这么加:(栈顶元素加上上一个元素的高度差)

image.png

image.png

第二步结束之后其实栈里只有两根柱子:(单调栈初具雏形)

image.png

3.再加一根,形不成凹槽

image.png

4.下一根,需要加上一个凹槽

image.png

5.下一步加上这个

image.png

6.最后一步

image.png

7.我们最后可以来个最高的

image.png

此时栈中元素:(绿色的)

image.png 加上面积:

image.png

确实很难想!

代码:

class Solution {
    public:
        int trap(vector<int>& height) {
            stack<int> stk;
            int res = 0;
            for (int i = 0; i < height.size(); i ++ ) {
                // 这里有个巧妙的地方,就是当last为0的时候,第一次res+的是0,因为(i - stk.top() - 1)肯定是0,所以last的初始值取多少都行
                int last = 0;
                while (stk.size() && height[stk.top()] <= height[i]) {
                    res += (height[stk.top()] - last) * (i - stk.top() - 1);
                    last = height[stk.top()];
                    stk.pop();
                }

                if (stk.size()) res += (i - stk.top() - 1) * (height[i] - last);
                stk.push(i);
            }

            return res;
        }
};