IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode 42 接雨水(单调栈,动态规划,双指针) -> 正文阅读

[数据结构与算法]LeetCode 42 接雨水(单调栈,动态规划,双指针)

题目描述
给定 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

方法一:单调栈
雨水存在的地方是低洼的地方,维护一个单调栈,栈内存储的元素是数组的下标,如果遍历到的元素值 height[i] 大于栈顶元素,那么此时可以形成一个低洼的地方,因此需要计算该低洼的地方的高和宽。首先删除栈顶元素。

  • 高度:可以承接雨水的左右两个柱子的此时height[i] 与 新的栈顶元素之间的最小值,然后减去删除的栈顶元素所对应的高度值。为啥要减去栈顶元素对应的高度值呢?每次求解加的是一个横向的矩形,可以结合[4,6]区间的雨水计算方法理解。
  • 宽度是当前下标元素减去新的栈顶元素然后减去1,表示当前柱子 i (右边界)与左边柱子(左边界)之间的距离。
  • 时间复杂度和空间复杂度都为O(n)
class Solution {
public:
    int trap(vector<int>& height) {
       int n=height.size();
       stack<int> stk;
       int res=0;
       for(int i=0;i<n;i++)
       {
           while(!stk.empty()&&height[stk.top()]<height[i])
           {
               int t=stk.top();
               stk.pop();
               if(!stk.empty())
               {
                   int h=min(height[i],height[stk.top()])-height[t];
                   int w=i-stk.top()-1;
                   res+=h*w;
               }
           }
           stk.push(i);
       }
       return res;
    }
};

方法二:动态规划

在这里插入图片描述
在这里插入图片描述
如图所示,从左向右找到该位置 i 处左边最大的值,从右往左找到位置 i 处右边最大的值,求解雨水的过程如第二张图所示,在left_max和right_max中取最小值然后减去当前位置的height[i] 即可。

class Solution {
public:
    int trap(vector<int>& height) {
       int n=height.size();
       if(!n) return 0;
       int res=0;
       vector<int> left(n,0); left[0]=height[0];
       vector<int> right(n,0); right[n-1]=height[n-1];
       for(int i=1;i<n;i++)
       {
           left[i]=max(height[i],left[i-1]);
       }
       for(int i=n-2;i>=0;i--)
       {
           right[i]=max(height[i],right[i+1]);
       }
       for(int i=0;i<n;i++)
       {
           res+=min(left[i],right[i])-height[i];
       }
       return res;
    }
};

方法三:双指针
动态规划是将位置 i 处左右两边的最大值保存在了数组中,现在可以使用双指针减少了空间复杂度,使用leftmax保存位置left处的左边最大值,使用rightmax保存位置right处右边的最大值,以左指针为例,如果该位置处的值大于leftmax,那么更新leftmax,否则会形成一个低洼的地段,此时可以计算雨水的面积了,计算面积的时候是按照一列一列来计算的,因此只需要考虑高度即可,因此是leftmax-height[left],之后left向右移动。右指针类似。
可以看到双指针与动态规划方式本质上是类似的,都是寻找位置 i 处的左边最大值和右边最大值,只不过省去了取min的操作,原因在于如果height[left]<height[right]那么要更新leftmax和rightmax时,leftmax肯定小于rightmax,因此只需要在leftmax这边操作即可,相当于动态规划中的min(left[i],right[i])操作。

class Solution {
public:
    int trap(vector<int>& height) {
       int left=0,right=height.size()-1;
       int res=0;
       int leftmax=0,rightmax=0;
       while(left<right)
       {
           if(height[left]<height[right])
           {
               if(height[left]>leftmax) leftmax=height[left];
               else res+=leftmax-height[left];
               left++;
           }
           else
           {
               if(height[right]>rightmax) rightmax=height[right];
               else res+=rightmax-height[right];
               right--;
           }
       }
       return res;
    }  
};
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-16 11:33:17  更:2021-07-16 11:35:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 15:59:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码