题目:

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. 开始nodejs+express的学习+实践(1)

    开始nodejs+express的学习+实践(1) 开始nodejs+express的学习+实践(2) 开始nodejs+express的学习+实践(3) 开始nodejs+express的学习+实践 ...

  2. 现在有一张半径为r的圆桌,其中心位于(x,y),现在他想把圆桌的中心移到(x1,y1)。每次移动一步,都必须在圆桌边缘固定一个点然后将圆桌绕这个点旋转。问最少需要移动几步。

    // ConsoleApplication5.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<vector> ...

  3. 允许局域网内其他主机访问本地MySql数据库

    mysql的root账户,我在连接时通常用的是localhost或127.0.0.1,公司的测试服务器上的mysql也是localhost所以我想访问无法访问,测试暂停. 解决方法如下: 1,修改表, ...

  4. Easy AR简单教程

    Easy AR简单教程 相关SDK资源下载链接:http://pan.baidu.com/s/1dERtCWD   密码:o0jd 1.ImageTarget的制作 (1).导入EasyARSD包,删 ...

  5. python 基础 1.5 python 数据类型(一)--整型 浮点型 布尔型及字符串和常用方法

    一.python 数据类型:数值,字符串,列表,元组,字典.以下操作是在linux 下 ipython中进行 1.数值 1>123  与  “123”的区别 答:123为数值,“123”在pyt ...

  6. 【BZOJ3834】[Poi2014]Solar Panels 分块好题

    [BZOJ3834][Poi2014]Solar Panels Description Having decided to invest in renewable energy, Byteasar s ...

  7. framemarker的使用

    1 什么是framemarker framemarker是网页模版和数据模型的结合体.装载网页的时候,framemarker自动从数据模型中提取数据并生成html页面. 2 framemarker怎么 ...

  8. 10分钟看懂, Java NIO 底层原理

    目录 写在前面 1.1. Java IO读写原理 1.1.1. 内核缓冲与进程缓冲区 1.1.2. java IO读写的底层流程 1.2. 四种主要的IO模型 1.3. 同步阻塞IO(Blocking ...

  9. FastJson 技术

    最近开始做淘宝的开放平台.阿里巴巴FastJson是一个Json处理工具包,包括“序列化”和“反序列化”两部分,它具备如下特征: 速度最快,测试表明,fastjson具有极快的性能,超越任其他的Jav ...

  10. Java for LeetCode 108 Convert Sorted Array to Binary Search Tree

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 解题 ...