leetcode 接雨水I II

本文深入探讨了经典的“接雨水”算法问题,通过三种不同的方法:双指针、备忘录和栈保存,详细解释了如何计算二维数组中能够储存多少雨水。每种方法都附有详细的代码实现,帮助读者理解并掌握这一算法的核心思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

双指针

  • 根据木桶原理,储水量由最短边决定
  • 我们使用两个指针,分别向左向右扫描,保存左右边的最高高度
  • 如果height[l] < height[r] 即右边高度高,则储水量由左边高度确定,反之相反
class Solution {
public:
    int trap(vector<int>& height) {
        int lmax=0,rmax=0;
        int res = 0;
        int l=0,r=height.size()-1;
        while(l<=r){
            if(height[l]<height[r]){
                lmax = max(height[l],lmax);
                res += lmax-height[l];
                l++;
            }else{
                rmax = max(height[r],rmax);
                res += rmax-height[r];
                r--;
            }
        }
        
        return res;
    }
};

备忘录

  • 遍历两次数组,分别记录每个位置 左右的最小木板高度
  • 然后由min(left,right)-height[i]决定当前位置储水量

class Solution {
public:
    int trap(vector<int>& height) {
        int len = height.size();
        vector<int> left(len),right(len);

        for(int i=1;i<len;i++){
            left[i] = max(left[i-1],height[i-1]);
        }
        for(int i=len-2;i>=0;i--){
            right[i] = max(right[i+1],height[i+1]);
        }
        int res = 0;
        for(int i=1;i<len-1;i++){
            int level = min(left[i],right[i]);
            res += max(0,level-height[i]);
        }
        return res;
    }
};

栈保存






407 接雨水II

在这里插入图片描述

接雨水1,我们保存左右两边最小的木板高度,短边决定储水量

  1. 这个二维数组,我们则需要统计 四边的最短木板, 可以使用堆(优先队列)维护四边最短木板
  2. 然后由外围向内延伸,如果找到比当前队列中短边更小的位置,则可以储水,同时更新最短边高度
  3. 直到每个位置都访问完毕即可, 在遍历过程中,使用数组标记已访问,避免重复计算
class Solution {
public:
    struct node{
        int x,y,h;
        node(int x,int y,int h):x(x),y(y),h(h){};
    };

    struct cmp{
        bool operator ()(node* o1,node* o2){
            return o1->h > o2->h;
        }
    };

    int trapRainWater(vector<vector<int>>& heightMap) {
        priority_queue<node*,vector<node*>,cmp> q;
        if(heightMap.size() < 3|| heightMap[0].size()<3) return 0;
        int row=heightMap.size(),col=heightMap[0].size();

        vector<vector<bool>> dp(row,vector<bool>(col,false));
        for(int i=0;i<row;i++){
            q.push(new node(i,0,heightMap[i][0]));
            dp[i][0]=true;
            q.push(new node(i,col-1,heightMap[i][col-1]));
            dp[i][col-1] = true;
        }
        for(int i=1;i<col-1;i++){
            q.push(new node(0,i,heightMap[0][i]));
            dp[0][i]=true;
            q.push(new node(row-1,i,heightMap[row-1][i]));
            dp[row-1][i]=true;
        }

        int res = 0;
        int dirs[4][2] = {{1,0},{0,-1},{0,1},{-1,0} };
        while(!q.empty()){
            node* cur = q.top();
            q.pop();
            int x=cur->x;
            int y=cur->y;
            int h=cur->h;
            for(int d=0;d<4;d++){
                int nx=x+dirs[d][0];
                int ny=y+dirs[d][1];
                if(nx<0||nx>=row|| ny<0||ny>=col || dp[nx][ny]) continue;
                if(h > heightMap[nx][ny]){
                    res += h-heightMap[nx][ny];
                    heightMap[nx][ny] = h;
                }
                q.push(new node(nx,ny,heightMap[nx][ny]));
                dp[nx][ny] = true;
            }
        }
        return res;
    }
};

11. 盛最多水的容器

class Solution {
public:
    int maxArea(vector<int>& height) {
        int res = 0;
        if(height.empty()) return res;
        int l=0,r=height.size()-1;
        while(l<r){
            int level = min(height[l],height[r]);
            res = max(res,level*(r-l));
            if(height[r]>height[l]) l++;
            else r--;
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值