攒青豆

85 阅读2分钟

攒青豆

当青训营遇上码上掘金 刚开始看到这道题的时候有一点没有头绪,最开始的想法是有没有可能一层一层算,计算两个柱子中间有多少空,因为是一层一层算的,所有有空就加一,但是这样的话时间复杂度会比较大,因为每层都要遍历整个数组一遍,所以这种想法就放弃了,然后继续思考,查资料,想起来之前做过一道类似的题,是下雨求攒的雨水,和这题类似,所以查了下,是一道经典题,有一些解析,因为最高的和最低的之间最多的青豆只能是最低的,并且每一个最低的旁边的青豆都是能和他一平的,所以选出最高的,然后以最高的为分界线,从左向最高的遍历,再从右向最高的遍历,假设当前高度是h,数组元素下移高度为x,如果x比h高那么他俩之间不会有青豆,当前高度就更新为x的,如果x比h低,那所攒的青豆就是h-x,因为继续遍历肯定会有一个最高点,那么当前高度h和最高点之间一定会有x高的青豆,,至少这一条是肯定会有的,然后高度还是h,继续遍历数组,从左向最高点遍历一次,再从右向最高点遍历一次,就能求出最终结果。

step就是当前高度,首先遍历数组找出最高点,然后记录最高点元素下标,以他为中心,把数组分开,首先从左(第一个元素)向最高点遍历,如果当前数组元素高度x(为了简写,x指的是height[i])高于此时高度step,那么x和step之间不可能有青豆(自行理解),所以step更新成当前高度x,然后继续向下遍历数组,如果数组元素高度x小于step,那么他们之间就有step-x这么多青豆,那就记录到总数里,直到遍历到最高点

然后从右(最后一个元素)向最高点遍历,同理

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    int height[n];
    for(int i=0;i<n;i++){
        cin>>height[i];
    }
        if(n==0) {
            return 0;
        }
        int step = 0;
        int rains = 0;
        int maxHeightI = 0;
        int maxHeight = height[0];
        for(int i=1;i<=n-1;i++) {
            if(height[i] > maxHeight) {
                maxHeight = height[i];
                maxHeightI = i;
            }
        }
        for(int i=0;i<=maxHeightI;i++) {
            if(height[i] > step) {
                step = height[i];
            } else if(height[i] < step){
                rains += step - height[i];
            }
        }
        step = 0;
        for(int i=n-1;i>maxHeightI;i--) {
            if(height[i] > step) {
                step = height[i];
            } else if(height[i] < step){
                rains += step - height[i];
            }
        }
        cout<<rains<<endl;
        return 0;  
}