这道题的解题思路其实不是很难,我们需要考虑的是对于每一个柱形图它的左右两端所能到达的最远距离,什么意思呢,我们以第二个柱形图1考虑,它的左边柱形图2比它高,所以它能到达的左边最远距离为1,同理它到达最右边的是最后一个柱形图,因为都比他高,那么他的面积就是(1 + 1 + 4) * 1。我们在看高度为5的柱形图,可以看到他的左边柱形图是1比他矮所以它不能到达,我们看它的右边柱形图也就是找第一个比他小的柱形图。我们看到6比它高,而下一个2比他矮,所以它只能到达6,因此它的面积(0 + 1 + 1) * 5。因此我们只需要计算出每一个柱形图它所能到达的最远边界是多少即可求出,但是如果不加以技巧很容易超时,再来讨论区看到一个小技巧(大牛就是厉害),具体代码如下我们自信分析下:
class Solution { public: int largestRectangleArea(vector<int>& heights) { int m = heights.size(); if(m==0) return 0; vector<int>left(m, 0); vector<int>right(m, 0); left[0] = -1; int area = 0; int res = 0; for (int i = 1; i < m; i++) { int p = i - 1; while (p >= 0 && heights[p] >= heights[i]) p = left[p]; left[i] = p; } for (int i = m - 1; i >= 0; i--) { int p = i + 1; while (p < m && heights[p] >= heights[i]) p = right[p]; right[i] = p; } for (int i = 0; i < m; i++) { area = heights[i] * (right[i] - left[i] - 1); res = max(res, area); } return res; } };我们看到定义里两个left和right数组是为了求解左边界和右边界问题,但是其实我们可以利用之前计算的结果而不用每次都需要遍历。 int p = i - 1; while (p >= 0 && heights[p] >= heights[i]) p = left[p]; left[i] = p; 我们来看这个while循环,如果条件成立,也就是说,当前柱形图的高度比他左边的低,那么我们可以利用索引找到第一个比他小的,因为left [ p ]记录的是第p个柱形图的左边比他矮的第一个柱形图,这里可能说的比较拗口,但是仔细想一下确实是这样的,这么做其实就是索引的跳级查找,因此这个while是一个常量级的循环,与整个柱形图数量没有直接关系。这是整个代码的精华所在,因此需要仔细想一想。