C练题笔记之:Leetcode-42. 接雨水

本文介绍了LeetCode第42题《接雨水》的解题思路,通过从前往后和从后往前两次遍历数组,计算能接收到的雨水量。文中详细解释了如何利用变量记录最高柱子的下标和储水格子的数量,以及如何计算出水量。代码实现简洁明了,适合C语言初学者学习。

题目:

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 
示例 2:

输入:height = [4,2,0,3,2,5]
输出:9
 

提示:

n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

结果:

用栈实际上也只是一个数据进栈,不过不知道为啥耗时又差距。 

解题思路:

因为就算用栈,实际上存储的也是一个数据,所以这里用变量的方法说。

topHigh:变量用于存储目前最大的柱子所在下标。

trapSum:用于存储目前为止储水格子数量。

tempSum:用于存储目前位置柱子格子数量。

一、从前往后遍历

        本次需要遍历到最后:

        如果当前柱子比记录的柱子矮,则将柱子高度所占格子数量增加到tempSum中。

        如果当前柱子比记录的柱子高或者相等:

                本次出水量sum = (当前下标 - 之前最高柱子下标 - 当前柱子占用格子宽度1) * 之前柱子高度 -  这个之间所有柱子格子数。

                因为当前柱子是高于等于之前柱子高度的,因此能最大出水的高度是之前柱子的高度。

二、从后往前遍历

        第二次遍历的时候,后面最高柱子就是之前遍历完存储在topHigh的柱子,因此我们只需要遍历到这个柱子就可以停止了。

        从后面开始遍历,逻辑和第一遍一样,仅仅是停止循环的位置提前了。

        本次出水量sum = (之前最高柱子下标 - 当前下标 - - 当前柱子占用格子宽度1) * 之前柱子高度 -  这个之间所有柱子格子数。

代码:

/* 用变量记录 */
int trap(int* height, int heightSize){
    int topHigh = 0;
    int trapSum = 0;
    int tempSum = 0;

    // 从前到最高处位置的出水量计算
    for (int i = 1; i < heightSize; i++) {
        if (height[i] < height[topHigh]) {
            tempSum += height[i];
        } else {
            int sum = (i - topHigh - 1) * height[topHigh] - tempSum;
            trapSum += sum;
            tempSum = 0;
            topHigh = i;
        }
    }

    // 从后往最高柱子位置的出水量
    int rTopHigh = topHigh;
    tempSum = 0;
    topHigh = heightSize - 1;
    for (int i = topHigh - 1; i >= rTopHigh; i--) {
        if (height[i] < height[topHigh]) {
            tempSum += height[i];
        } else {
            int sum = (topHigh - i - 1) * height[topHigh] - tempSum;
            trapSum += sum;
            tempSum = 0;
            topHigh = i;
        }
    }
    return trapSum;
}


/*
int trap(int* height, int heightSize){
    int *stack = (int *)malloc(sizeof(int) * heightSize);
    int top = -1;
    int trapSum = 0;
    int tempSum = 0;

    // 从前到最高处位置的出水量计算
    for (int i = 0; i < heightSize; i++) {
        if (top == -1) {
            stack[++top] = i;
            continue;
        }
        if (height[i] < height[stack[top]]) {
            tempSum += height[i];
        } else {
            int sum = (i - stack[top] - 1) * height[stack[top]] - tempSum;
            trapSum += sum;
            tempSum = 0;
            top = 0;
            stack[top] = i;
        }
    }

    // 从后往最高柱子位置的出水量
    int topHigh = stack[top];
    tempSum = 0;
    top = -1;
    for (int i = heightSize - 1; i >= topHigh; i--) {
        if (top == -1) {
            stack[++top] = i;
            continue;
        }
        if (height[i] < height[stack[top]]) {
            tempSum += height[i];
        } else {
            int sum = (stack[top] - i - 1) * height[stack[top]] - tempSum;
            trapSum += sum;
            tempSum = 0;
            top = 0;
            stack[top] = i;
        }
    }
    return trapSum;
}
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值