两道求最大面积的题目在解法上的不同

今天发现两道看似十分相似但实际上有很大不同的题目,差点转不过弯来,分别是LeetCode 11 盛最多水的容器LeetCode 84 柱状图中最大的矩形

LeetCode 11 盛最多水的容器

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器。

LeetCode 84 柱状图中最大的矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

我先写了84题,再回过头写11题时,以为两道题的区别就是柱状图和“挡板”的区别,还是用单调栈的方法,只需在求面积的时候做一点小修改即可。

先看84题。从左往右遍历柱状图的每一个柱形,若当前遍历到的柱形比上一个柱形高,则无法确定以上一个柱形的高为高的最大矩形面积,因为矩形可以越过当前柱形,一直延伸到右边,而右边的情况还不知道;反之,若当前遍历到的柱形比上一个柱形低,则以上一个柱形的高为高的矩形肯定无法越过当前柱形,又因为其左侧所有柱形已经遍历过了,所以矩形能够延伸到的左右两边的极限都可以确定,以上一个柱形的高为高的最大矩形面积也确定下来了。实际上,以当前柱形左侧的所有比当前柱形高的柱形的高为高的最大矩形面积都可以确定下来了。上述算法可以通过栈实现,栈中依次存储所有以第i个柱形为高的矩形的最大面积还未确定时的i值。

解决了第84题,我把代码套到第11题的时候发现无论我怎么修改边界条件,得出来的结果与答案都相去甚远。再次读题目的时候发现两道题有一个很大的不同:在第11题中,若确定了左右边界i、j,则所得矩形的高为min{height[i], height[j]},换言之,水可以漫过挡板i、j中间的挡板;但在第84题中,所得矩形的高还受柱形i、j中间的柱形的限制,其值为min{height[i], height[i + 1], …, height[j - 1], height[j]},换言之,柱形相当于容器,水不能超出容器,而且水的形状必须是矩形,可以将其理解为“冰块”

因此,第11题只要确定了左右边界i、j,就可以确定矩形的面积,故遍历时使用双指针即可。