栈方法
class Solution {
public int largestRectangleArea(int[] heights) {
int[] new_heights = new int[heights.length + 1];
Deque<Integer> stack = new LinkedList<Integer>();
stack.addLast(0);
int max_area = 0;
for(int i = 0; i < heights.length; i++){
new_heights[i] = heights[i];
}
new_heights[heights.length] = 0;
for(int i = 0; i < new_heights.length; i++){
while (!stack.isEmpty() && new_heights[stack.peekLast()] > new_heights[i]){
int peek = stack.removeLast();
while (!stack.isEmpty() && new_heights[stack.peekLast()] == new_heights[peek]){
peek = stack.removeLast();
}
int left = stack.isEmpty() ? 0 : stack.peekLast() + 1;
max_area = Math.max(new_heights[peek] * (i - left), max_area);
}
stack.addLast(i);
}
return max_area;
}
}
分治算法
class Solution {
public int calculateArea(int[] heights, int start, int end){
if(start > end){
return 0;
}
int min_i = start;
for(int i = start; i <= end; i++){
if(heights[min_i] > heights[i]){
min_i = i;
}
}
return Math.max(heights[min_i] * (end - start + 1),
Math.max(calculateArea(heights, start, min_i - 1),
calculateArea(heights, min_i + 1, end)));
}
public int largestRectangleArea(int[] heights) {
return calculateArea(heights, 0, heights.length - 1);
}
}
线段树 + 分治算法
class SegTreeNode{
public int start_;
public int end_;
public SegTreeNode l_;
public SegTreeNode r_;
public int min_;
SegTreeNode(){}
SegTreeNode(int start, int end){
this.start_ = start;
this.end_ = end;
this.l_ = this.r_ = null;
}
}
class Solution {
public SegTreeNode buildTree(int[] heights, int start, int end){
if(start > end) return null;
SegTreeNode root = new SegTreeNode(start, end);
if(start == end){
root.min_ = start;
return root;
}
int mid = (start + end) / 2;
root.l_ = buildTree(heights, start, mid);
root.r_ = buildTree(heights, mid + 1, end);
root.min_ = heights[root.l_.min_] < heights[root.r_.min_] ? root.l_.min_ : root.r_.min_;
return root;
}
public int query(SegTreeNode root, int[] heights, int start, int end){
if(root == null || start > root.end_ || end < root.start_) return -1;
if(start <= root.start_ && end >= root.end_){
return root.min_;
}
int left_min = query(root.l_, heights, start, end);
int right_min = query(root.r_, heights, start, end);
if(left_min == -1) return right_min;
if(right_min == -1) return left_min;
return heights[left_min] < heights[right_min] ? left_min : right_min;
}
public int calculateArea(SegTreeNode root, int[] heights, int start, int end){
if(start > end){
return -1;
}
if(start == end){
return heights[start];
}
int min_i = query(root, heights,start, end);
int left_max = calculateArea(root, heights, start, min_i - 1);
int right_max = calculateArea(root, heights, min_i + 1,end);
return Math.max(heights[min_i] * (end - start + 1),
Math.max(left_max, right_max));
}
public int largestRectangleArea(int[] heights) {
if(heights.length == 0) return 0;
SegTreeNode root = buildTree(heights, 0, heights.length - 1);;
return calculateArea(root, heights, 0, heights.length - 1);
}
}