当青训营遇上码上掘金--接雨水 ** 攒青豆

57 阅读1分钟

主题 4:攒青豆

n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

攒青豆.png

看到这张图片就能联想到"接雨水"那道题,废话不多说,直接说思路。

思路一

在接雨水那道题中,我们经常用按列计算的思路解题,在攒青豆中同样可以用这个思路。

直接预处理每一个柱子,对于每一个柱子来说,找向左(右)走能被拦下的最大高度,然后再遍历一遍左右数组,找到最小值与h[i]的差,并累加到答案中。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;

vector<int> height;

int solve() {
    int n = height.size(), ans = 0;
    if (n == 0)
        return 0;
    // 预定义两个数组,存放每个点向左、向右能够围成的最大高度。
    vector<int> left_max(n), right_max(n);
    // 向左走
    left_max[0] = height[0];
    for (int i = 1; i < n; i++) 
        left_max[i] = max(left_max[i - 1], height[i]);
    // 向右走
    right_max[n - 1] = height[n - 1];
    for (int i = n - 2; i >= 0; i--)
        right_max[i] = max(right_max[i + 1], height[i]);
    // 累加答案
    for (int i = 0; i < n; i++)
        ans += min(left_max[i], right_max[i]) - height[i];

    return ans;
}


int main()
{
    int t;
    // height = vector<int>{5,0,2,1,4,0,1,0,3};
    while(~scanf("%d", &t))
    {
        height.push_back(t);
    }
    printf("%d\n", solve());
    
    return 0;
}

思路二

思路二其实是对思路一的一个优化。

可以看到,max_left [ i ] 和 max_right [ i ] 数组中的元素其实只用到了一次。所以可以不用数组,优化空间,只用一个元素就行了。

代码参考:42. 接雨水 - 力扣(Leetcode)

public int trap(int[] height) {
    int sum = 0;
    int max_left = 0;
    int max_right = 0;
    int left = 1;
    int right = height.length - 2; // 加右指针进去
    for (int i = 1; i < height.length - 1; i++) {
        //从左到右更
        if (height[left - 1] < height[right + 1]) {
            max_left = Math.max(max_left, height[left - 1]);
            int min = max_left;
            if (min > height[left]) {
                sum = sum + (min - height[left]);
            }
            left++;
        //从右到左更
        } else {
            max_right = Math.max(max_right, height[right + 1]);
            int min = max_right;
            if (min > height[right]) {
                sum = sum + (min - height[right]);
            }
            right--;
        }
    }
    return sum;
}