LeetCode传送门 https://leetcode.com/problems/trapping-rain-water/

目标:找出积木能容纳的水的“面积”,如图中黑色部分是积木,蓝色为可容纳水的部分

假设:积木宽度均为1

输入:各个积木的高度

输出:所有积木能容纳水的“面积”

思考过程

1. 逐一求积木的间隔似乎不太容易。特别对于图中3-7积木间的容积,如果可以先求底部(4-6间)的容积,当求解上层(3-7)的容积时,还需要做额外的处理,如减掉底部的高度。

2. 既然如此,可否先求出3-7间整体的容积,再将两积木之间的积木面积(4、5、6)减去,即可得这个区域的容积?

3. 那么问题转换成了,已知一个积木,如何寻找下一个积木,并计算这个两积木间的容积

4. 尝试一,寻找一个至少不比当前积木低的积木,作为下一个积木,如图例子为当前积木3,下一个积木7。那么之间的容积如何计算呢,简单,积木3的高度乘以两积木间的间隔宽度,再减去,积木3与积木7之间的积木(4、5、6)面积。

5. 问题:下次迭代从何开始?上一个例子,可以从积木7继续算起。然而如果找不到相应的积木呢,那么从积木3的下一个积木4开始。

6. 看起来,似乎正确。于是乎,开始写代码了。然而第一次提交就献给了WA(/(ㄒoㄒ)/~~)

7. 错误的情况,如果当前的积木是一个特别高的积木,后继找不到更高的积木,然而实际上之间是可能有容积的!不赘述了,补救思路是:在寻找更高的积木的同时,记录当前找到的最高的积木。如果没有找到更高的积木,使用当前找到的最高的积木作为下一个积木,并计算容积。

思路总结

迭代的过程

1. 寻找下一个至少不比当前积木低的积木,寻找的同时,记录当前找到的最高的积木高度

2. 如果找到,则计算两积木之间的容积(计算过程见思考过程2)

3. 如果没有找到,则计算当前积木与当前找到的最高的积木之间的容积

4. 当前积木设置为找到的积木(可能是2或3的情况),继续迭代

时间复杂度

O(n)

代码实现

 #include <iostream>
#include <vector> using namespace std; class Solution {
public:
int trap(vector<int>& height) {
if (height.size() == ) {
return ;
} int water = ;
int preIndex = ;
int preHeight = ; // 找到第一个高度非0的bar
while (preIndex < height.size() - && height[preIndex] == ) {
++preIndex;
} if (preIndex == height.size() - ) {
return ;
} // 遍历
while (preIndex < height.size()) {
preHeight = height[preIndex]; // 寻找更高的或相等的bar
// 同时记录遍历过的最高的bar
// 如果寻找不到更高的或相等的bar时,使用记录值计算
int next = preIndex + ;
int minHeight = ;
int minIndex = next; while (next < height.size() && height[next] < preHeight) {
if (height[next] > minHeight) {
minHeight = height[next];
minIndex = next;
}
++next;
} // 如果找到
if (next != height.size()) {
water += (preHeight * (next - preIndex - )); // 计算总面积 for (int i = preIndex + ; i < next; ++i) { // 减去中间bar面积
water -= height[i];
} preIndex = next; // 从找到的bar开始下一次的迭代
} else {
water += (minHeight * (minIndex - preIndex - )); // 计算总面积 for (int i = preIndex + ; i < minIndex; ++i) { // 减去中间bar面积
water -= height[i];
} preIndex = minIndex; // 从次高的bar开始
}
} return water;
}
}; int main(int argc, char const *argv[]) {
Solution solution;
vector<int> height = {,,,,,,,,,,,};
cout << solution.trap(height) << endl;
return ;
}

Trapping Rain Water

闲聊一二

大年初一!祝大家猴年快乐啦,已经工作的童鞋升职加薪,要实习、找工作的童鞋offer多多~博主今年也要面对找实习、找工作的人生大事儿了。好久没写博客了,默默的哀悼上个学期,自己瞎折腾,弄出的不成熟的东西。希望猴年是激情,奋斗,收获的一年~

ps:有没有对我感兴趣的boss收留~附交友地址一枚https://github.com/zrss

简单粗暴的resume:https://github.com/zrss/ghostblog,近期再修改下

有意思的数学题:Trapping Rain Water的更多相关文章

  1. leetcode#42 Trapping rain water的五种解法详解

    leetcode#42 Trapping rain water 这道题十分有意思,可以用很多方法做出来,每种方法的思想都值得让人细细体会. 42. Trapping Rain WaterGiven n ...

  2. [LeetCode] Trapping Rain Water II 收集雨水之二

    Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevati ...

  3. [LeetCode] Trapping Rain Water 收集雨水

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

  4. [LintCode] Trapping Rain Water 收集雨水

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

  5. LeetCode:Container With Most Water,Trapping Rain Water

    Container With Most Water 题目链接 Given n non-negative integers a1, a2, ..., an, where each represents ...

  6. LeetCode - 42. Trapping Rain Water

    42. Trapping Rain Water Problem's Link ------------------------------------------------------------- ...

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

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

  8. [array] leetcode - 42. Trapping Rain Water - Hard

    leetcode - 42. Trapping Rain Water - Hard descrition Given n non-negative integers representing an e ...

  9. 【LeetCode】42. Trapping Rain Water

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

随机推荐

  1. [ES6] ... spread operator

    var parts = ['shoulders', 'knees']; var lyrics = ['head', ...parts, 'and', 'toes']; // ["head&q ...

  2. [转] IPC之管道、FIFO、socketpair

    管道和FIFO作为最初的UNIX IPC形式,现在已用得较少.SocketPair可作为全双工版本的管道,较为常用,这里简单做个笔记 管道 * 只用于有亲缘关系的进程间通信 * 单向,即半双工 (双向 ...

  3. Android组件系列----BroadcastReceiver广播接收器

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...

  4. 小学生之Java中迭代器实现的原理

    一. 引言 迭代这个名词对于熟悉Java的人来说绝对不陌生.我们常常使用JDK提供的迭代接口进行java collection的遍历: Iterator it = list.iterator();wh ...

  5. OD: Windows Kernel Debug

    内核调试入门 内核程序运行在内核态,因此不能像对用户态应用程序那样来调试.关于内核调试方面的知识请参考<软件调试>这本书.目前内核调试主要有以下三种方法. 一是使用硬件调试器,它通过特定的 ...

  6. 一条insert语句批量插入多条记录

    一条insert语句批量插入多条记录 常见的insert语句,向数据库中,一条语句只能插入一条数据: insert into persons (id_p, lastname , firstName,  ...

  7. SVN库迁移整理方法总结

    有时候需要从一台机器迁移svn存储库到另外一台机器,如果数据量非常大的话,没有好的方法是很不方便的,其实迁移svn跟迁移mysql差不多,也有导出导入的方案 以下是subversion官方推荐的备份方 ...

  8. Struts2 UI标签

    表单标签的共同属性(该属性只在没有使用 simple 主题时才可以使用) form 标签  用来呈现 HTML 语言中的表单元素 默认情况下, form 标签将被呈现为一个表格形式的 HTML 表单. ...

  9. 武汉科技大学ACM :1008: 华科版C语言程序设计教程(第二版)习题6.14

    Problem Description 输入一个八进制的字符串,将它转换成等价的十进制字符串,用pringf的%s格式输出. Input 首先输入一个正整数t,表示有t组测试数据(1<= t & ...

  10. C++拾遗(七)函数相关(2)

    内联函数 内联函数与常规函数的区别在于: 1.常规函数:在执行调用指令时,先存储该指令的内存地址,将函数参数复制到堆栈,然后跳转到被调用函数起点的内存单元,执行函数,将返回值放 入寄存器,最后跳回到一 ...