題目:給出一個直方圖(如圖所示),求出所給直方圖中所包含的最大矩陣面積。直方圖可以用一個整數數組表示,如上圖爲[2, 1, 5, 6, 2, 3]。每個直方塊的寬度均爲1。上圖中包含的最大矩陣面積爲10。來源:http://www.jiuzhang.com/problem/43/
解題思路:如果對於每個直方塊,找到從它開始往左邊數第一個比它小的,和往右邊數第一個比他小的,則可以確定出以該直方塊爲最矮一塊的矩陣的最大面積。使用數據結構棧,棧中保存遞增序列,從左到右依次遍歷每個數讓其入棧,入棧之前先pop出所有>=該數的數,從而保持棧中的遞增序列。pop完之後的棧頂元素即爲該數往左邊數第一個比他小的數。同理反過來遍歷一次可以得到往右邊數第一個比他小的數。時間複雜度O(n),空間複雜度O(n)。
代碼實現:
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class Rectangle {
private int index;
private int height;
private int left;
private int right;
@Override
public String toString() {
return "Rectangle [height=" + height + ", index=" + index + ", left="
+ left + ", right=" + right + "]";
}
protected static int getMaxRectangle(List<Rectangle> lists){
Stack<Rectangle> stack = new Stack<Rectangle>();
//輸入檢測
if(lists == null || lists.size() == 0){
System.out.println("非法輸入!");
System.exit(0);
}
//從左往右入棧
for(int i = 0; i < lists.size(); i++){
Rectangle rectangle = lists.get(i);
while(!stack.isEmpty() && stack.peek().height >= lists.get(i).height){
stack.pop();
}
if(stack.isEmpty()){
rectangle.left = 0;
}else {
rectangle.left = stack.peek().index;
}
lists.set(i, rectangle);
stack.push(rectangle);
}
stack.clear();
//從右往左入棧
for(int i = lists.size() - 1; i >= 0; i--){
Rectangle rectangle = lists.get(i);
while(!stack.isEmpty() && stack.peek().height >= lists.get(i).height){
stack.pop();
}
if(stack.isEmpty()){
rectangle.right = lists.size() + 1;
}else {
rectangle.right = stack.peek().index;
}
lists.set(i, rectangle);
stack.push(rectangle);
}
//計算面積最大值
int max = (lists.get(0).right - lists.get(0).left - 1)*lists.get(0).height;
System.out.println(lists.get(0));
for(int i = 1; i < lists.size(); i++){
int temp = (lists.get(i).right - lists.get(i).left - 1)*lists.get(i).height;
System.out.println(lists.get(i));
if(max < temp){
max = temp;
}
}
return max;
}
public static void main(String[] args) {
int [] values = new int[]{2, 1, 5, 6, 2, 3};
List<Rectangle> lists = new ArrayList<Rectangle>();
for (int i = 0; i < values.length; i++) {
Rectangle rectangle = new Rectangle();
rectangle.height = values[i];
rectangle.index = i + 1;
lists.add(rectangle);
}
System.out.println(Rectangle.getMaxRectangle(lists));
}
}