接雨水 , 给定二维图,能容多少水

42. 接雨水 - 力扣(LeetCode)

看着就是非常常规的题目,所以非常有必要掌握。

最少也把O(n^2)的方法写出来吧。力扣官方题解的三种方法O(n)都挺好,不过可能有点难读,在此经过学习,写一篇自己的通俗理解。

0.O(n^2)

每次只看单个格子,这个格子能放多少水呢?

只要左边和右边都比自己高,就能放水了。

所以对于每个格子,分别找到最左和最优最高的,(根据木桶原理。。)此格子能放的水就是较低的那个。

class Solution {
public:
    map<int,int>mm;
    int trap(vector<int>& height) 
    {
        int ret = 0;
        int n = height.size();
        for(int i=0;i<n-1;i++)
        {
            int r;
            int maxv = 0,maxo = 0;
            for(r=i+1;r<n;r++)
            {
                if(height[r]>=height[i])
                    break;

                if(height[r] >= maxv)
                {
                    maxv = height[r];
                    maxo = r;
                }
            }
            if(r>=n)
            {
                int aim = maxv;
                for(int j = i+1;j<maxo;j++)
                {
                    if(height[j]<aim)
                        ret += aim - height[j];
                }
                i = maxo-1;
            }
            else
            {
                int aim = min(height[i],height[r]);
                for(int j = i+1;j<r;j++)
                {
                    if(height[j]<aim)
                        ret += aim - height[j];
                }
                i = r-1;
            }
        }
        return ret;
    }
};

1.动态规划

其实跟背包问题差别蛮大的。

看题解这张图其实就很好懂:

左往右遍历一次,右往左遍历一次,取覆盖区域并集即可。(哇这是动归吗)

class Solution {
public:
    map<int,int>mm;
    int trap(vector<int>& height) 
    {
        int n = height.size();
        vector<int>l(n),r(n);
        int tmp = 0;
        for(int i=0;i<n;i++)
        {
            tmp = max(tmp,height[i]);
            l[i] = tmp;
        }
        tmp = 0;
        for(int i=n-1;i>=0;i--)
        {
            tmp = max(tmp,height[i]);
            r[i] = tmp;
        }
        int ret = 0;
        for(int i=0;i<n;i++)
        {
            ret += min(l[i],r[i]) - height[i];
        }
        return ret;
    }
};

2.单调栈

是这样的一个解法。

如果多格高:

单调栈内放下标,他们的高度 从栈底到栈顶 是降低的。

直到遇见一个高的,那么栈顶的就可以作底去装水,高度为左边和右边较低者。

class Solution {
public:
    stack<int>sti;
    int trap(vector<int>& height) 
    {
        int n = height.size();
        int ret = 0;
        for(int i=0;i<n;i++)
        {
            while(sti.size()&&height[i] > height[sti.top()])
            {
                //这个是放水的平面
                int top = sti.top(); sti.pop();
                if(sti.size() == 0)break;//挨着的 | 上升的

                //补的是和左边这个高度差

                ret += (i-sti.top()-1) * (min(height[sti.top()],height[i]) - height[top]);
            }            
            sti.push(i);
        }
        return ret;
    }
};

3.双指针

和1类似,是对0的优化,不用每次都挨着找一遍。官方题解写法我看不太懂。但思想是明确的。

我们找左边最大 leftmax和右边最大 rightmax,那么中间就是容器能装水啦。

我们从低的一边向另一边走,遇到的格子能放的水都最多到低的这边的高度。

比如 leftmax <= rightmax ,左向右,每个格子都能装水到 leftmax。

直到遇见高边,且这个高边比右边最高还高,就可以从右向左了。

不然就一直往右装水:

class Solution {
    //其实右边有足够高的,左边底的绝对都能放进去水
public:
    int trap(vector<int>& height) 
    {
        int n = height.size();
        int l = 1,r = n-2;
        int leftmax = height[0],rightmax = height[n-1];
        int ret = 0;
        while(l<=r)
        {
            while(leftmax <= rightmax&&l<=r)
            {
                if(height[l] < leftmax)
                    ret += leftmax - height[l];
                else
                    leftmax = height[l];
                l++;
            }
            
            while(leftmax > rightmax&&l<=r)
            {
                if(height[r] < rightmax)
                    ret += rightmax - height[r];
                else
                    rightmax = height[r];
                r--;
            }
        }
        return ret;
    }
};

相关推荐

  1. 【困难】42. 雨水

    2024-04-21 14:44:02       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-21 14:44:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-21 14:44:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-21 14:44:02       82 阅读
  4. Python语言-面向对象

    2024-04-21 14:44:02       91 阅读

热门阅读

  1. spring生成递增key值

    2024-04-21 14:44:02       43 阅读
  2. 多个gradio服务实现负载均衡

    2024-04-21 14:44:02       104 阅读
  3. 后端自测帮助指南

    2024-04-21 14:44:02       34 阅读
  4. AcWing 800. 数组元素的目标和——算法基础课题解

    2024-04-21 14:44:02       38 阅读
  5. RIP协议

    RIP协议

    2024-04-21 14:44:02      36 阅读
  6. 深度学习基础——残差神经网络(ResNet)

    2024-04-21 14:44:02       40 阅读