问题描述:在下图里我们有不同高度的挡板。这个图片由一个整数数组所代表,数组中每个数是墙的高度。下图可以表示为数组(2、5、1、2、3、4、7、2)。假如开始下雨了,那么挡板之间的水坑能够装多少水(水足够多)呢?

下图是装满水的情况,一个蓝色格子代表一个单位的水。下图中一共装了10个单位的水。

问题分析:

先看看下图,判断哪个单元格的水能留下来。下图中的两个单元格,一个红色的单元格和一个绿色的单元格,哪个单元格的水是溜走了,哪个单元格的水能留下来?

很明显的,上图中的红色单元格的水会流走,绿色单元格的水会被留下来。

那么,仔细看看这两个单元格的区别在哪儿

区别就是,红色单元格只有右边的挡板比它高(不低于它),而绿色单元格左右两边都有挡板比它高(左边最高是5,右边最高是7)

这也就很好的理解了,如果水要能留下来,必须左右两边的挡板都比它高才行。(很明显的,不管哪一侧的挡板比水低,水就会朝哪个方向流出去)

于是,我给每个挡板定义了3个属性

V属性:本挡板的高度

L属性:本挡板左侧挡板的最高高度

R属性:本挡板右侧挡板的最高高度

那么,该挡板上方能积水的充要条件就是:L>V并且R>V

如果该挡板能积水,则积水量为:Min(L-V,R-V)

那么总的积水量就是所有挡板的积水量总和

问题就变成,如何求出每块挡板的L属性和R属性

用V、L、R三个数组标示挡板组的三个属性。一共有N块挡板,数组的下标从0到N-1。

V(i)表示第i块挡板的高度、L(i)表示第i块挡板的L属性、R(i)表示第i块挡板的R属性

可知的是L(0)=0,R(N-1)=0;

不失一般性,考虑第i块挡板的L属性(i>0)。L(i-1)表示第i-1块挡板的L属性。那么,可知

如果L(i-1)>V(i-1),则L(i)=L(i-1)

如果L(i-1)≤V(i-1),则L(i)=V(i-1)

综上所述:L(i)=Max(L(i-1),V(i-1))(i>0)

同理可述:R(i)=Max(R(i+1),V(i+1))(i<N-1)

而由于L(0)=0,R(N-1)=0。则说明第0、N块挡板(最左和最右的挡板)是不会积水的

因此,计算L和R的属性以及计算积水量的下标从1开始到N-2即可

代码如下:

Public Class clsFillWater
    Public Shared Function FillWater2(ByVal ParamArray Nums() As Integer) As Integer
        Dim L(Nums.Length - 1) As Integer
        Dim R(Nums.Length - 1) As Integer
        Dim I As Integer
        Dim Result As Integer = 0

If Nums.Length < 3 Then Return 0

L(0) = 0
        R(Nums.Length - 1) = 0

For I = 1 To Nums.Length - 2
            L(I) = Math.Max(L(I - 1), Nums(I - 1))
            R(Nums.Length - 1 - I) = Math.Max(R(Nums.Length - I), Nums(Nums.Length - I))
        Next

For I = 1 To Nums.Length - 2
            If L(I) > Nums(I) AndAlso R(I) > Nums(I) Then
                Result += Math.Min(L(I), R(I)) - Nums(I)
            End If
        Next

Return Result
    End Function
End Class

从代码看,该算法的时间效率是O(N)的,是线性时间的。在文章 Twitter算法面试题详解(Java实现) 的评论中也有一个线性时间的算法(效率相当,可能还优于本算法),不过理解上不如这个简单明了。

算法实践——Twitter算法面试题(积水问题)的线性时间解法的更多相关文章

  1. Twitter算法面试题详解(Java实现)

    最近在网上看到一道Twitter的算法面试题,网上已经有人给出了答案,不过可能有些人没太看明白(我也未验证是否正确),现在给出一个比较好理解的答案.先看一下题目. 图1 先看看图图1.可以将方块看做砖 ...

  2. 【转】Twitter算法面试题详解(Java实现)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://androidguy.blog.51cto.com/974126/1319659 ...

  3. 【BAT经典算法面试题系列】求和为n的连续正整数

    马上就要到9月份了,意味着一年一度的秋招就要开始了,相信不论是正在实习的童鞋还是马上就要找工作的童鞋,BAT无疑是国内的"明星企业",是每个学计算机的小伙伴们心之向往的企业,但是呢 ...

  4. 华为Python 算法面试题

    华为算法面试题 """ 算法题: 提供一个序列,完成对这个序列的分割.要求分割后的两个序列彼此差值最小 实现函数,返回两个序列 """ de ...

  5. 算法面试题:一个List<Student>,要求删除里面的男生,不用Linq和Lamda,求各种解,并说明优缺点!

    算法面试题:一个List,要求删除里面的男生,不用Linq和Lamda,求各种解,并说明优缺点! 解题思路 这是群里某位小伙伴去面试碰到的面试题,从题目本身来看,面试官应该是要考察面试者对泛型 Lis ...

  6. Java算法面试题(史上最强、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  7. 常见的js算法面试题收集,es6实现

    1.js 统计一个字符串出现频率最高的字母/数字 let str = 'asdfghjklaqwertyuiopiaia'; const strChar = str => { let strin ...

  8. LeetCode 算法面试题汇总

    LeetCode 算法面试题汇总 算法面试题 https://leetcode-cn.com/problemset/algorithms/ https://leetcode-cn.com/proble ...

  9. 奇妙的算法【11】LeetCode-专属算法面试题汇总

    这个是LeetCode上面的编程训练专项页面,地址:https://leetcode-cn.com/explore/interview/card/top-interview-quesitons-in- ...

随机推荐

  1. 造完美的go开发环境

    http://www.cnblogs.com/qgymje/p/3912259.html   这篇原来是给公司里使用go开发的交流用的,主要是工具的安装,用markdown写的,发布了内部gitlab ...

  2. mysql学习笔记 第七天

    数据库的备份与还原 数据库的备份与还原是后面章节的内容,但是在学习的时候已经需要数据的备份与还原了,所以就了解了一下.数据库有很多种备份方法,我学习的是其中的一种 备份: 对于数据库的备份: C:&g ...

  3. How Tomcat Works读书笔记之升级架构

    上一篇HttpServer类职责很多,包括启动服务器,创建ServerSocket,得到客户端Socket,创建Request对象和Response对象,并解析Http请求,这样很混乱,不利于以后服务 ...

  4. 浏览器-Tomcat服务器-请求与响应

    浏览器访问服务器,本质就是请求资源. 比如请求静态资源:index.html,我们在浏览器地址栏输入:www.a.com/index.html,浏览器为了支持HTTP协议,发送的数据必须符合HTTP协 ...

  5. [moka同学摘录]Yii2.0开发初学者必看

    想要了解更多YII,PHP方面内容,请关注本博客. 基础总结 1.修改默认控制器/方法 yii默认是site控制器,可以在web.php中设置$config中的'defaultRoute'='xxxx ...

  6. <s:iterator>各种遍历用法

    struts2<S:iterator>遍历map小结 1.MapAction.java import java.util.ArrayList;   import java.util.Has ...

  7. ASP.NET Core 1.0开发Web API程序

    .NET Core版本:1.0.0-rc2Visual Studio版本:Microsoft Visual Studio Community 2015 Update 2开发及运行平台:Windows ...

  8. osx的终端软件iterm2 之 修改外观 和 常用快捷键小结

    1.修改外观:透明,自己配色,最好还有个透明的小背景,比如这样: 那么你就要这样修改: 2.快捷键小结 (1)⌘ + d 横着分屏 / ⌘ + shift + d 竖着分屏  : 适合多操作的时候 ( ...

  9. Android studio 快捷添加构造方法以及set与get

    第一种方式 快捷键: Alt + lnsert (笔记本可能没有后面的按键) 按快捷键会出现下面这个页面: 第二种方式:点开后是跳出上面那个选择框

  10. PHP控制前台弹出对话框

    应用场景: 微信授权登录过程中,需要用户确认,故衍生此需求: 相应的逻辑不放在前端的原因是,此部分逻辑属于偏功能业务,所以放在后端,方便统一管理. 解决办法: 通过php echo出javascrip ...