2020秋招笔试—最大海报面积
—LeetCode.84变体
题目
输入两个长度为n的数组,分别为n个矩形条的宽和高,现在要在这些矩形覆盖的面积内找到一个最大的矩形面积来张贴海报。
说明:输入参数有任何错误和非法数据时,返回0。
示例:
输入:
x=[1,1,1,1,2,1,1];
y=[5,2,5,4,5,1,6];
n=7
输出:
16
思路
本题就是LeetCode.84的变体,比较好的思路就是维护一个单调栈,栈内存储对应的矩形块索引。因此,求解本题需要有几个关键点:
- 建立宽度一致的矩形条高度数组 ,将矩形条索引统一成数组的下标;
- 维护一个单调栈:当栈顶元素(数组下标)对应的矩形高度ht 小于当前遍历的矩形高度hi时,将该矩形索引入栈;大于当前遍历的矩形高度时,将栈顶元素弹出至栈顶元素对应矩形高度不再大于当前遍历的矩形高度hi,这时再将当前遍历到的索引入栈;至于等于则不需要向栈压入数据。这就维护了一个单调栈,保证站内索引对应的高度都是递增的。
- 从前向后遍历高度数组,每弹出一个栈顶元素,则代表有一个高度ht的矩形延伸到了尽头,需要记录一次索引位置,此时获得的是对应高度的左极限位置;当数组遍历到结尾时,需要将栈清空,反向遍历高度数组,获取右极限位置。
- 计算面积:Si = (右极限位置 - 左极限位置 - 1) * hi,维护一个最大值缓存,每次计算完毕都与其比较,将较大值更新;
- 计算完毕,返回最大值缓存。
代码
// An highlighted block
public int largestRectangleArea(int[] xArray,int[] yArray){
if(xArray.length<=0||yArray.length<=0||xArray.length!=yArray.length)
return 0;
int[] heights = getHeights(xArray,yArray);
int ans = getMaxAreaOfRectangle(heights);
return ans;
}
private int getMaxAreaOfRectangle(int[] heights){
int n=heights.length;
int[] left = new int[n];
int[] right = new int[n];
Stack<Integer> stack = new Stack<>();
for(int i=0;i<n;i++){
while (!stack.isEmpty()&&heights[stack.peek()]>=heights[i])
stack.pop();
left[i] = stack.isEmpty()?-1:stack.peek();
stack.push(i);
}
stack.clear();
for(int i=n-1;i>=0;--i){
while (!stack.isEmpty()&&heights[stack.peek()]>=heights[i])
stack.pop();
right[i] = stack.isEmpty()?n:stack.peek();
stack.push(i);
}
int ans = 0;
for (int i=0;i<n;++i)
ans = Math.max(ans,(right[i]-left[i]-1)*heights[i]);
return ans;
}
private int[] getHeights(int[] xArray,int[] yArray){
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i<xArray.length;i++){
int tempX = xArray[i];
while (tempX-->0){
list.add(yArray[i]);
}
}
int[] heights = new int[list.size()];
int index = 0;
for(int num:list){
heights[index++] = num;
}
return heights;
}
图的话等以后熟练了再补啦。