leetcode 42,407 接雨水问题的总结

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

先说比较简单的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 

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

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

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

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

原文地址:https://www.cnblogs.com/heisenberg-/p/15507816.html