博文中会简要介绍Leetcode P0042题目分析及解题思路。
“Trapping Rain Water”是一道非常经典的问题,在很多面试中都会出现,也属于原型题之一。这篇博文主要介绍动态规划的做法,比较简单直接。C++代码实现了使用栈(单调栈)的解法,有一些具体注释,这里不再赘述。使用栈的解法相对于用动态规划的解法,在思维上相对要复杂一些。
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.
下面重点讲解动态规划的思路。仔细读题后我们不难发现,想要得到以某一个bar
为底座的储水量,需要知道这个bar
左边最高的高度和右边最高的高度,然后取这两个高度中的较小值,用这个较小值与当前这个bar
的高度作差就能得到这个bar
为底座的储水量了。
为什么需要知道左右端的最大高度呢?
原因其实很简单,如果我们假定右端高度无穷大,那么左端的高度越高,以该bar
为底座,宽度为1的上方的储水量也就越多,也就是说储水量取决于左端(也是较小端,因为右端高度是无穷大),同理右端,所以找到左右端最大高度。而实际的储水量则取决于这两个高度中的较小值,也是前面说到的取决于较小端。于是我们就得到了计算储水量的方法。
那么如何快速地得到左右两端的最大值呢?我们可以使用动态规划的思维,即一个bar
左端的最大值一定等于这个bar
前面一个bar
的左端最大值和这个bar
自身的高度中的较大值,也即:
这样一来我们就得到每个bar
左端的最大高度,同理我们也可以得到每个bar
右端的最大值,然后计算储水量,使用两端最大高度中的较小值作为实际水面即可。
以下是Java的题解代码实现。
以下是实现了单调栈解法的C++题解代码实现。