力扣每日一题——接雨水

题目描述

给定 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 个单位的雨水(蓝色部分表示雨水)。

解法一------动态规划

在给出的数组中,为了求可以接到雨水的量,我们可以遍历数组,找到下标i处左右两侧的最高值之差,将每个点处的雨水量想加,即为所求值,所以我们可以利用两个数组来分别存放下标i处的左右最高值

代码如下

cs 复制代码
int min(int a,int b)
{
    if(a>=b)
    {
        return b;
    }
    else
    {
        return a;
    }
}
int trap(int* height, int heightSize) {
    int l=heightSize;
    printf("%d",l);
    int left_data[l];
    int right_data[l];
    for(int i=0;i<l;i++)
    {
        left_data[i]=0;
        right_data[i]=0;
    }
    int temp=height[0];
    for(int i=0;i<l;i++)
    {
        if(temp<height[i])
        {
            temp=height[i];
        }    
        left_data[i]=temp;    
    }
    temp=height[l-1];
    for(int i=l-1;i>=0;i--)
    {
        if(temp<height[i])
        {
            temp=height[i];
        }
        right_data[i]=temp;
    }
    int sum=0;
    for(int i=0;i<l;i++)
    {
        int a=min(left_data[i],right_data[i]);
        if(a>height[i])
        {
            sum+=a-height[i];
        }
    }
    return sum;
}

解法二------栈

在题中,只有在低洼处才会聚集雨水,所以我们可以利用单调栈来解决这个问题,在栈中存入下标值,便于查找

遍历数组,将数据下标按照值单调递减的逻辑进行入栈,当当前下标的数据值大于栈顶元素的数据值,进行一系列操作,当一次遍历结束后,sum值即为所求

操作:

1.先将栈顶元素出栈并存储,新的栈顶元素便是低洼处的左边的下标值,遍历的下标值i是低洼处的右边的下标值,所以低洼处的高度为二者想减再减一,高度为二者的数据值的最小值再减去低洼处自身的高度值

2.一直持续上述操作,直到栈为空或栈中元素满足单调递减的逻辑,将雨水值依次相加

代码如下

cs 复制代码
int min(int a,int b)
{
    if(a<=b)
        return a;
    else
        return b;
}
int trap(int* height, int heightSize) {

    int l=heightSize;
    int stack[l];
    int top=-1;
    int sum=0;
    for(int i=0;i<l;i++)
    {
        while(top!=-1&&height[stack[top]]<height[i])
        {
            int temp=stack[top];
            top--;
            if(top==-1)
            {
                break;
            }
            int le=stack[top];
            sum+=(i-le-1)*(min(height[i],height[le])-height[temp]);
        }
        top++;
        stack[top]=i;
    }
    return sum;
}

解法三------双指针

这个解法的关键就是首先要确立一个较高的值来作为左边界或右边界,当已经确立了一个边界时,无论是向右遍历还是向左遍历,都只需要判断当前下标的高度值是否小于上一个遍历下标的高度值即可,其实这里的指针并非是真正的指针,只是两个用来做判断的标志

代码如下

cs 复制代码
int trap(int* height, int heightSize) {
    int sum=0;
    int left=0;
    int right=heightSize-1;
    int max_l=0;
    int max_r=0;
    while(left<right)
    {
        if(height[left]<height[right])
        {
            if(height[left]>max_l)
            {
                max_l=height[left];
            }
            else
            {
                sum+=max_l-height[left];
            }
            left++;

        }   
        else
        {
            if(height[right]>max_r)
            {
                max_r=height[right];
            }
            else
            {
                sum+=max_r-height[right];
            }
            right--;
        }     
    }
    return sum;
}
相关推荐
Tisfy17 分钟前
LeetCode 2333.最小差值平方和:排序 + 数学计算(不用二分)
数学·算法·leetcode·题解·贪心·排序
aqiu11111120 分钟前
【C++算法打怪专栏】LeetCode 217. 存在重复元素(解法总结)
c++·算法·leetcode
iotxiaohu34 分钟前
用 cflow 查看 C 函数调用关系
c语言·开发语言·cflow
yi0112 小时前
DAY28: LeetCode 111. 二叉树的最小深度
人工智能·笔记·python·算法·leetcode·二叉树·递归
wuyk5552 小时前
27.LeetCode 2265. 统计值等于子树平均值的节点数 —— 后序遍历实战
stm32·单片机·嵌入式硬件·算法
xiangyun612 小时前
C++ list 模拟实现(二):const迭代器与反向迭代器,模板的黑魔法
开发语言·数据库·c++·算法·stl·list
xxwl5852 小时前
三、区域赛算法模版第三章---字符串相关算法
笔记·学习·算法
信奥卷王2 小时前
[GESP202509 六级] 划分字符串(含视频)
数据结构·算法
酒醉的胡铁3 小时前
相似度搜索的常见算法
算法·ai
局部有解3 小时前
Leetcode Hot100 - 最长连续序列
算法·leetcode·职场和发展