题目描述
有一个直方图,用一个整数数组表示,其中每列的宽度为1,求所给直方图包含的最大矩形面积。比如,对于直方图[2,7,9,4],它所包含的最大矩形的面积为14(即[7,9]包涵的7x2的矩形)。
给定一个直方图A及它的总宽度n,请返回最大矩形面积。保证直方图宽度小于等于500。保证结果在int范围内。
测试样例:
[2,7,9,4,1],5
返回:14
思路
1、首先确定范围,在特定范围中,这个区域的面积为:长度 x 所有列中高度最低那一列的高度
2、一开始的范围是所有列计算面积,然后找出最低的列,以此列为基准分为左右两边,再递归计算左右两边的面积。
3、因为要想超过原先区域的面积值,毕定要求新选取的区域不能包含那个最低的列,如果包含那么高度依然是这个最低的列的高度,但长度缩短了,因此一定会更小。所以只有去掉这个最低列再去选择范围才有可能找出更大的面积(如果存在的话)
代码
public class MaxInnerRec {
public int countArea(int[] A, int n)
{
return maxArea(A, 0, n-1);
}
private int maxArea(int[] A, int left, int right)
{
// left > right说明对原先区域而言左边或右边已经没有了,不可再分出左或右区域了
if (left > right) return 0;
// left = right说明这一块区域(对原先而言可以是左边也可以是右边)只有一列,那此列的高度既是面积
if (left == right) return A[left];
// 找出此区域的高度最低的列。
int highIndex = findMin(A, left, right);
// 计算此范围内的做大面积
int max = (right - left + 1) * A[highIndex];
// 计算最低高度的列的左边区域的最大面积并与此区域最大面积比较,选更大的
max = Math.max(max, maxArea(A, left, highIndex - 1));
// 计算最低高度的列的右边区域的最大面积并与此区域最大面积比较,选更大的
max = Math.max(max, maxArea(A, highIndex + 1, right));
return max;
}
// 寻找直方图局部范围中最低的列的下标
private int findMin(int[] A, int left, int right)
{
int min = left;
for (int i = left + 1; i <= right; i++)
if (A[i] < A[min]) min = i;
return min;
}
}
注:是参考牛客大佬的思路,其个人主页:https://www.nowcoder.com/profile/642207