Hard!

题目描述:

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

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

解题思路:

先来看一种方法,这种方法是基于动态规划Dynamic Programming的,我们维护一个一维的dp数组,这个DP算法需要遍历两遍数组,第一遍遍历dp[i]中存入i位置左边的最大值,然后开始第二遍遍历数组,第二次遍历时找右边最大值,然后和左边最大值比较取其中的较小值,然后跟当前值A[i]相比,如果大于当前值,则将差值存入结果。

C++解法一:

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

最后我们来看一种只需要遍历一次即可的解法,这个算法需要left和right两个指针分别指向数组的首尾位置,从两边向中间扫描,在当前两指针确定的范围内,先比较两头找出较小值,如果较小值是left指向的值,则从左向右扫描,如果较小值是right指向的值,则从右向左扫描,若遇到的值比当前较小值小,则将差值存入结果,如遇到的值大,则重新确定新的窗口范围,以此类推直至left和right指针重合。

C++解法二:

 class Solution {
public:
int trap(vector<int>& height) {
int res = , l = , r = height.size() - ;
while (l < r) {
int mn = min(height[l], height[r]);
if (mn == height[l]) {
++l;
while (l < r && height[l] < mn) {
res += mn - height[l++];
}
} else {
--r;
while (l < r && height[r] < mn) {
res += mn - height[r--];
}
}
}
return res;
}
};

我们可以对上面的解法进行进一步优化,使其更加简洁。

C++解法三:

 class Solution {
public:
int trap(vector<int>& height) {
int l = , r = height.size() - , level = , res = ;
while (l < r) {
int lower = height[(height[l] < height[r]) ? l++ : r--];
level = max(level, lower);
res += level - lower;
}
return res;
}
};

下面这种解法是用stack来做的。其实用stack的方法更容易理解,我们的做法是,遍历高度,如果此时栈为空,或者当前高度小于等于栈顶高度,则把当前高度的坐标压入栈,注意我们不直接把高度压入栈,而是把坐标压入栈,这样方便我们接下来计算水平距离。

当我们遇到比栈顶高度高的时候,就说明有可能会有坑存在,可以装雨水。此时我们栈里至少有一个高度,如果只有一个的话,那么不能形成坑,我们直接跳过,如果多于一个的话,那么此时把栈顶元素取出来当作坑,新的栈顶元素就是左边界,当前高度是右边界,只要取二者较小的,减去坑的高度,长度就是右边界坐标减去左边界坐标再减1,二者相乘就是盛水量了。

C++解法四:

 class Solution {
public:
int trap(vector<int>& height) {
stack<int> st;
int i = , res = , n = height.size();
while (i < n) {
if (st.empty() || height[i] <= height[st.top()]) {
st.push(i++);
} else {
int t = st.top(); st.pop();
if (st.empty()) continue;
res += (min(height[i], height[st.top()]) - height[t]) * (i - st.top() - );
}
}
return res;
}
};

LeetCode(42):接雨水的更多相关文章

  1. Java实现 LeetCode 42 接雨水

    42. 接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这 ...

  2. [LeetCode]42. 接雨水(双指针,DP)

    题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下, ...

  3. leetcode 42. 接雨水 JAVA

    题目: 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下 ...

  4. Leetcode 42.接雨水

    接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下 ...

  5. Leetcode 42 接雨水 双指针

    地址 https://leetcode-cn.com/problems/trapping-rain-water/ 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能 ...

  6. LeetCode 42. 接雨水(Trapping Rain Water)

    题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况 ...

  7. LeetCode(42.接雨水)多解法详解

    接雨水解法详解: 题目: 基本思路:从图上可以看出要想接住雨水,必须是凹字形的,也就是当前位置的左右两边必须存在高度大于它的地方,所以我们要想知道当前位置最多能存储多少水,只需找到左边最高处max_l ...

  8. LeetCode 42接雨水 按行求解(差分+排序)

    按行求解的思路比较清晰明了,但是这个方法的复杂度高达O(heightSize*sum(height[i])),几乎高达O(N^2). 但是也并不是不可以解决,经观察我们可以发现,这个算法的缺点在于要遍 ...

  9. 每日一题 LeetCode 42.接雨水 【双指针】

    题目链接 https://leetcode-cn.com/problems/trapping-rain-water/ 题目说明 题解 主要方法:双指针 + 正反遍历 解释说明: 正向遍历:先确定池子左 ...

  10. LeetCode:接雨水【42】

    LeetCode:接雨水[42] 题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1, ...

随机推荐

  1. django基础之数据库操作

    Django 自称是“最适合开发有限期的完美WEB框架”.本文参考<Django web开发指南>,快速搭建一个blog 出来,在中间涉及诸多知识点,这里不会详细说明,如果你是第一次接触D ...

  2. brctl创建虚拟网卡详解

    brctl创建虚拟网卡详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 很久之前我分享过一篇关于搭建Openvpn的笔记,在笔记的最后我分享了一个脚本,是用来创建虚拟网卡的,今天 ...

  3. js通用绑定事件函数

  4. Mabatis三剑客分别是:mybatis-generator、mybatis-plugin、mybatis-pagehelper

    本文用的是maven,idea15 Mabatis三剑客分别是:mybatis-generator.mybatis-plugin.mybatis-pagehelper 一.mybatis-genera ...

  5. Gym - 100269F Flight Boarding Optimization(dp+树状数组)

    原题链接 题意: 现在有n个人,s个位置和你可以划分长k个区域你可以把s个位置划分成k个区域,这样每个人坐下你的代价是该区域内,在你之前比你小的人的数量问你怎么划分这s个位置(当然,每个区域必须是连续 ...

  6. 让富文本编辑器支持复制doc中多张图片直接粘贴上传

    Chrome+IE默认支持粘贴剪切板中的图片,但是我要发布的文章存在word里面,图片多达数十张,我总不能一张一张复制吧? 我希望打开文档doc直接复制粘贴到富文本编辑器,直接发布 感觉这个似乎很困难 ...

  7. 地图上道路编号中的G S X Y

    地图上道路中的G S X Y Z C D,分别表示什么道? 国道 省道 县道 乡道 专用道路 村道 D: 还没有搞明白

  8. javaScript事件系统详解

    一个有情怀的猴子

  9. Spring MVC 源码分析

      Spring MVC SpringMVC中扮演关键角色的DispatcherServlet类. 1 DispatcherServlet 1.1DispatcherServlet 类图 1.2 初始 ...

  10. [CQOI2018]交错序列 (矩阵快速幂,数论)

    [CQOI2018]交错序列 \(solution:\) 这一题出得真的很好,将原本一道矩阵快速幂硬生生加入组合数的标签,还那么没有违和感,那么让人看不出来.所以做这道题必须先知道(矩阵快速幂及如何构 ...