这两个关于接雨水的问题并没有涉及到很复杂的算法和数据结构,但是解这两个问题的思想是比较有趣的,可以放在一起做一个一般化的讨论。

 

先说比较简单的leetcode42, 给定n个宽度相同的柱子高度的高度,每一个柱子可以作为相邻柱子的挡板,问最多能承接多少水。

 

比如 三个柱子的高度为[2,1,2] 则能承接一个单位的水。 

 

 

最简单高效的方法是维护左右侧的短板。 只需要两个指针就可以求得结果。

 

最初的短板即为1号板和n号板。

下一次应该更新哪个板子呢? 应该更新比较短的这一侧。 因为与它相邻的位置最高水位已经由它决定了。

 

比方说 [3,1,6,4], 第二个板的水位肯定不会超过3, 所以我们可以将左边的短板向右更新了。 问题就变成了求[3,6,4]的接水量, 最终结果要加上2。

 

这个就是leetcode42最简便的解法。

 

 

把这个问题扩展成二维后,也就是leetcode407,我们要维护的短板就不是左右侧的两个板,而是外围的一圈。 这一圈板中我们总是需要找到最短的那个板。

比方说

 

3 3 5 6

7 1 1  2

3 3 3 3

在这个情况中,最外围的短板是2,  它决定了与它相邻的柱子的最高水位, 然后我们就可以删去它,把问题简化

 

3 3 5 6

7 1 2

3 3 3 3 

于是,我们维护的外围变小了, 但我们依旧要很快的找到外围中的短板。

 

所以我们要使用优先队列或者小顶堆来维护外围。

 

总结一下,在一维的情况下,外围总是由两个板组成,我们可以直接进行比较在常数时间内找到短板。

在二维以上的情况下,外围则由许多板组成,我们需要一个数据结构来帮助我们快速地找到短板。