《LeetCode之每日一题》:105.接雨水

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:105.接雨水相关的知识,希望对你有一定的参考价值。

接雨水


题目链接: 接雨水

有关题目

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

示例 2:

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

n == height.length
0 <= n <= 3 * 10^4
0 <= height[i] <= 10^5

题解

法一:暴力法(超时)

int trap(int* height, int heightSize){
    int ans = 0;
    
    for (int i = 1; i < heightSize - 1; i++){
        //别忘记置零,放到外面可以拿[0,1,0,2,1,0,1,3,2,1,2,1]的元素2,3,2作为一个例子
        int leftMax = 0, rightMax = 0;
        for (int j = i; j >= 0; j--){
            leftMax = fmax(leftMax,height[j]);//当前坐标i左边的最大值
        }
        for (int k = i; k < heightSize; k++){
            rightMax = fmax(rightMax,height[k]);//当前坐标i右边的最大值
        }
        ans += fmin(leftMax,rightMax) - height[i];//记录答案
    }
    return ans;
}

法二:动态规划

思路:
结合上述暴力法求解接雨水的公式,
lmax[i]表示下标自0~i(包含端点)最大值
rmax[i]表示下标自i~n-1(包含端点)最大值
int trap(int* height, int heightSize){
    int n = heightSize;
    if (n == 0) return 0;
    int* lmax = (int*)malloc(sizeof(int) * n);
    memset(lmax,0,sizeof(int) * n);


    int* rmax = (int*)malloc(sizeof(int) * n);
    memset(rmax,0,sizeof(int) * n);
    int ans = 0;
    //初始值要结合我们动态规划所定义的数组来
    lmax[0] = height[0];
    rmax[n - 1] = height[n - 1];
    for (int i = 1; i < n; i++){
        lmax[i] = fmax(lmax[i - 1],height[i]);
    }

    for (int j = n - 2; j >= 0; j--){
        rmax[j] = fmax(rmax[j + 1],height[j]);
    }
    
    for (int i = 0; i < n; i++){
        ans += fmin(lmax[i],rmax[i]) - height[i];
    }
    return ans;
}


法三:单调栈

思路:
维护一个单调栈,单调栈存储的是下标,满足从栈底到栈顶的
下标对应的数组height元素递减
//C
int trap(int* height, int heightSize){
    int n = heightSize;
    if (n == 0) return 0;

    int ans = 0;
    int stk[n];
    int top = 0; //用这个来维护栈

    //注意到凹的趋势 
    for (int i = 0; i < n; i++){
        while(top && height[i] > height[stk[top - 1]]){
            int stk_top = stk[top - 1];
            top--;
            if (!top) break;//保证栈内至少存放两个下标
            
            int left = stk[top - 1];
            int curWidth = i - left - 1;
            int curHeight = fmin(height[i],height[left]) - height[stk_top];
            ans += curWidth * curHeight;
        }
        stk[top++] = i;
    }
    return ans;
}   

法四:双指针

int trap(int* height, int heightSize){
    int ans = 0;
    int l = 0, r = heightSize - 1;
    int lmax = 0, rmax = 0;
    while(l < r){
        lmax = fmax(lmax,height[l]);
        rmax = fmax(rmax,height[r]);
        if (lmax < rmax){
            ans += lmax - height[l];
            l++;
        } else {
            ans += rmax - height[r];
            r--;
        }
    }
    return ans;
}

以上是关于《LeetCode之每日一题》:105.接雨水的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 每日一题 42. 接雨水

LeetCode 每日一题「接雨水」

每日一题:42. 接雨水

LeetCode 575. 分糖果 / 237. 删除链表中的节点 / 407. 接雨水 II

leetcode题解之42. 接雨水

2021-07-15:接雨水 II。给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。