Trapping Rain Water

题目:一个数组代表一组相邻的柱子的高度,柱子的宽度都是1,求下雨后积水的面积。

多个柱子上的积水可能连成片,当成一块考虑比较复杂,思路不往复杂的方向走。还是考虑单独计算每一个柱子上的积水面积。从循环方便的角度也指向这个方向。

一个柱子上的积水高度由左边最高和右边最高的小者决定,即min(max_left, max_right) - current。有点像可以买卖2次的股票问题。

最直观的算法:遍历柱子,对于每个柱子分别计算左边的最高,和右边的最高,然后计算面积。如果是从左往右遍历,则左边的最高用一个变量维护就好,是O(1)的,右边的最高则需要一个O(n)的遍历,总得复杂度就是O(n*n)。

为了寻求O(n)的算法,

1)先从右往左遍历一遍,得到每个柱子右边最高的柱子高度,用一个数组保存起来。

2)再从左往右遍历,计算每个柱子左边最高的同时,结合第一步的数据,计算柱子上的积水面积并累加。

int trap(int A[], int n) {
    if (n <= 2) return 0;
    vector<int> max_right(n, 0);
    for(int i = n - 2; i >= 0; --i)
        max_right[i] = max(max_right[i + 1], A[i + 1]);

    int max_left = 0, sum = 0;
    for (int i = 1; i < n; ++i) {
        max_left = max(max_left, A[i - 1]);
        int height = min(max_left, max_right[i]);
        if (height > A[i])
            sum += height - A[i];
    }
    return sum;
}


最近发现的方法,双指针夹逼法,只需O(1)空间

int trap(vector<int>& height) {
    if (height.size() <= 2) return 0;
    int l = 0, r = height.size() - 1, lMax = 0, rMax = 0, area = 0;
    for (; l < r;) {
        lMax = max(lMax, height[l]);
        rMax = max(rMax, height[r]);
        if (lMax < rMax) {
            area += lMax - height[l];
            ++l;
        }
        else {
            area += rMax - height[r];
            --r;
        }
    }
    return area;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值