题目:

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

For example,

Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.

题解:

  遍历数组,找到局部最小值,方法是如果当前值大于或等于前一个值,或者当前值大于后一个值则跳过。找到了局部最小值后,然后向左找左边的最大值,再向右找右边的最大值,找右边最大值时要注意当其大于左边最大时就停止寻找。然后算出从左边最大值到右边最大值之间能装的水量,之后从右边最大值的位置开始继续找局部最小值,以此类推直到遍历完整个数组。(from here)Solution 1 中height[i] > height[i + 1]是为了避免若为>=,则数组为[5,5,1,7, 1, 1, 5,2,7,6]情况,没有=为23,有=为7;

Solution 1()

class Solution {
public:
int trap(vector<int>& height) {
int result = , n = height.size(), left = , right = ;
for(int i=; i<n-; i++) {
if(height[i] >= height[i-] || height[i] > height[i+]) continue;
for(left = i-; left>; --left) {
if(height[left]>=height[left-]) break;
}
right = i + ;
for(int j=i+; j<n; ++j) {
if(height[j]>=height[right]) {
right = j;
if(height[right]>=height[left]) break;
}
}
int h = min(height[left],height[right]);
for(int k=left+; k<right; ++k) {
if(h>height[k]) result += h - height[k];
}
i = right;
}
return result;
}
};

  对于每一个值,其与另外两个值组成的容器收集的雨水最大量肯定是在其左右两边的最大值作为容器的两个壁的情况下获得的,具体在题目里就是这两个最大值的较小值与当前值的差(当这个最小值大于当前值时,否则收集不到雨水)。使用动态规划,初始化一维数组vector<int> dp(n,0)。然后遍历两遍数组,第一次遍历从左边扫描找出当前位置左边的最大值,并存放到dp中;第二次遍历从右边扫描找出当前位置右边的最大值,然后与dp中保存的左边最大值比较,存下二者之中的较小值,并且将这个值与当前值比较,如果大于当前值,则收集的雨水总量应该加上这个较小值与当前值的差值。用一个数组 left[i] 表示第 i 根柱子左边最高的柱子的高度(from here
  用一个数组 right[i] 表示第 i 根柱子右边最高的柱子的高度
  1.从左到右扫描,left[i] = max(left[i - 1], A[i - 1])
  2.从右到左扫描,right[i] = max(right[i + 1], A[i + 1])
  3.第 i 根柱子上能储蓄的水为 min(left[i], right[i]) - A[i],因为这时 left[i] 已经没用了,可以用它来存放这个值。(from here
复杂度:时间O(n), 空间O(n)

Solution 2 ()  

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

  根据上面的雨水收集的分析,任意3个值组成的雨水收集量即是两边的较小值与中间值的差值(如果前者大于后者)。因此可以设置两个指针从两头往中间遍历,这两个指针所指的值即为容器的两个壁。低的壁(较小值)决定了收集雨水的量,因此中间值设为从较小值的后续值,并且算出收集的雨水,直到遇到一个值大于这个较小值,并且更新较小值为当前值。这样只需一趟扫描就可以解决问题。(from here

Solution 3 ()

class Solution {
public:
int trap(vector<int>& height) {
int result = , left = , right = height.size() - ;
while (left < right) {
int h = min(height[left], height[right]);
if (h == height[left]) {
++left;
while (left < right && height[left] < h) {
result += h - height[left++];
}
} else {
--right;
while (left < right && height[right] < h) {
result += h - height[right--];
}
}
}
return result;
}
};

  The idea is:

  1) find the highest bar.

  2) traverse the bar from left the highest bar.becasue we have the highest bar in right, so, any bar higher than its right bar(s) can contain the water.

  3) traverse the bar from right the highest bar.becasue we have the highest bar in left, so, any bar higher than its left bar(s) can contain the water. (from here ChenHao)

Solution 4 ()

class Solution {
public:
int trap(vector<int>& height) {
int result = , maxhigh = , maxidx = , n = height.size();
for(int i=; i<n; i++) {
if(height[i] > maxhigh) {
maxhigh = height[i];
maxidx = i;
}
}
int prehigh = ;
for(int i=; i<maxidx; ++i) {
if(height[i] > prehigh) {
prehigh = height[i];
}
result += (prehigh - height[i]);
}
prehigh = ;
for(int i=n-; i>maxidx; --i) {
if(height[i] > prehigh) {
prehigh = height[i];
}
result += (prehigh - height[i]);
} return result;
}
};

Solution 5 ()

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

【LeetCode】042 Trapping Rain Water的更多相关文章

  1. 【LeetCode】42. Trapping Rain Water

    Trapping Rain Water Given n non-negative integers representing an elevation map where the width of e ...

  2. 【LeetCode】42. Trapping Rain Water 接雨水 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力求解 保存左右最大值 单调栈 日期 题目地址:ht ...

  3. 【一天一道LeetCode】#42. Trapping Rain Water

    一天一道LeetCode系列 (一)题目 Given n non-negative integers representing an elevation map where the width of ...

  4. 【Lintcode】364.Trapping Rain Water II

    题目: Given n x m non-negative integers representing an elevation map 2d where the area of each cell i ...

  5. 【Lintcode】363.Trapping Rain Water

    题目: Given n non-negative integers representing an elevation map where the width of each bar is 1, co ...

  6. LeetCode 042 Trapping Rain Water

    题目要求:Trapping Rain Water Given n non-negative integers representing an elevation map where the width ...

  7. [Leetcode][Python]42: Trapping Rain Water

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 42: Trapping Rain Waterhttps://oj.leetc ...

  8. 【LeetCode题意分析&解答】42. Trapping Rain Water

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  9. LeetCode OJ 42. Trapping Rain Water

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

随机推荐

  1. 删除反复行SQL举例

    删除反复行SQL实验简单举例 说明:实验按顺序进行.前后存在关联性.阅读时请注意.打开文件夹更便于查看. 构造实验环境: SQL> select count(*) from emp;   COU ...

  2. FZU2125:简单的等式

    Problem Description 如今有一个等式例如以下:x^2+s(x,m)x-n=0. 当中s(x,m)表示把x写成m进制时,每一个位数相加的和.如今,在给定n,m的情况下,求出满足等式的最 ...

  3. 完好用户体验: 活用window.location与window.open解决页面跳转问题

    原文地址: JavaScript Redirects and window.open原文日期: 2014年08月27日翻译日期: 2014年08月31日翻译人员: 铁锚 (译者注: 本文解决的是按 C ...

  4. static修饰内部类

    创建内容类的方式通过外部类的实例对象来创建 public class AA { int a =1; class BB { int b=3 ; } public static void main(Str ...

  5. 初识python轻量web框架flask

    1.使用pip安装Python包 大多数Python包都使用pip实用工具安装,使用pyvenv创建的虚拟环境会自动安装pip. 1.使用pip安装Flask(其它Python包同理) pip ins ...

  6. TP框架部分---空控制器

    <?php namespace Admin\Controller; use Think\Controller; class DengLuController extends Controller ...

  7. 【BZOJ1604】[Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 Treap+并查集

    [BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000) ...

  8. 【BZOJ2597】[Wc2007]剪刀石头布 最小费用流

    [BZOJ2597][Wc2007]剪刀石头布 Description 在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之 ...

  9. mongo-connector导入数据到Es

    要求 基于mongo-connector同步数据,必须要求mongodb为复制集架构,原因是此插件是基于oplog操作记录进行数据同步的:而oplog可以说是Mongodb Replication的纽 ...

  10. vue 后台交互数据-编辑页面

    思路~点击编辑按钮,需要获取当前列的id,然后根据id请求后台当前id的数据 1.~~ 2.接收id,并请求页面 获取数据