- Largest Rectangle in Histogram
brute force O(n^2)
class Solution {
public int largestRectangleArea(int[] heights) {
// brute force
int max = 0;
for (int i = 0; i < heights.length; i++) {
int minHeight = heights[i];
for (int j = i; j < heights.length; j++) {
if (heights[j] < minHeight) {
minHeight = heights[j];
}
max = Math.max(max, minHeight * (j-i+1));
}
}
return max;
}
}
solution2: Divide and comque,类似merge sort的思路,但是速度没多大提升,占用的空间倒还因为recursion变多了
class Solution {
public int largestRectangleArea(int[] heights) {
// find the min of subarray
// spit as left part, min part, right part
// compute: maxarea(including min part), maxarea(left part), maxarea(right part)
// the maximum of these three parts is the maxarea
return helper(heights, 0, heights.length - 1);
}
public int helper(int[] heights, int start, int end) {
int len = end-start+1;
if (len == 0) {
return 0;
} else if (len == 1) {
return heights[start];
}
int minIdx = minIndex(heights, start, end);
int left = helper(heights, start, minIdx-1);
int right = helper(heights, minIdx+1, end);
int all = heights[minIdx] * (end - start + 1);
return Math.max(all, Math.max(left, right));
}
public int minIndex(int[] arr, int start, int end) {
int min = start;
for (int i = start + 1; i <= end; i++) {
if (arr[i] < arr[min]) {
min = i;
}
}
return min;
}
}
solution 3: stack : O(n) 还是无法理解
solution 4: the best solution
class Solution {
public int largestRectangleArea(int[] heights) {
int len = heights.length;
if (len == 0) {
return 0;
} else if (len == 1) {
return heights[0];
}
int[] lessFromLeft = new int[len];
int[] lessFromRight = new int[len];
lessFromLeft[0] = -1;
lessFromRight[len-1] = len;
for (int i = 1; i < len; i++) {
int p = i - 1;
while (p >= 0 && heights[p] >= heights[i]) {
p = lessFromLeft[p];
}
lessFromLeft[i] = p;
}
for (int i = len - 2; i >= 0; i--) {
int p = i + 1;
while (p < len && heights[p] >= heights[i]) {
p = lessFromRight[p];
}
lessFromRight[i] = p;
}
int maxArea = 0;
for (int i = 0; i < len; i++) {
maxArea = Math.max(maxArea, heights[i] * (lessFromRight[i] - lessFromLeft[i] - 1));
}
return maxArea;
}
}
- Maximal Rectangle
go to the solution of this question, it's really nice
solution 1:
class Solution {
public int maximalRectangle(char[][] matrix) {
// dynamic programming
// dp[i][j] represents the width of j in the ith row
if (matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int row = matrix.length, col = matrix[0].length;
int maxarea = 0;
int[][] dp = new int[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (matrix[i][j] == '1') {
if (j == 0) {
dp[i][j] = 1;
} else {
dp[i][j] = dp[i][j-1] + 1;
}
int width = dp[i][j];
for (int k = i; k >= 0; k--) {
width = Math.min(width, dp[k][j]);
maxarea = Math.max(maxarea, width * (i-k+1));
}
}
}
}
return maxarea;
}
}
solution 2:
dynamic programming
discussion‘reply
height counts the number of successive '1's above (plus the current one). The value of left & right means the boundaries of the rectangle which contains the current point with a height of value height.
class Solution {
public int maximalRectangle(char[][] matrix) {
if (matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int m = matrix.length, n = matrix[0].length;
int[] left = new int[n], right = new int[n], height = new int[n];
Arrays.fill(right, n-1);
int maxarea = 0;
for (int i = 0; i < m; i++) {
// update height
for (int j = 0; j < n; j++) {
if (matrix[i][j] == '1') {
height[j] += 1;
} else {
height[j] = 0;
}
}
// update left
int leftBoundry = 0;
for (int j = 0; j < n; j++) {
if (matrix[i][j] == '1') {
left[j] = Math.max(left[j], leftBoundry);
} else {
left[j] = 0;
leftBoundry = j + 1;
}
}
// update right
int rightBoundry = n-1;
for (int j = n-1; j >= 0; j--) {
if (matrix[i][j] == '1') {
right[j] = Math.min(right[j], rightBoundry);
} else {
right[j] = n-1;
rightBoundry = j-1;
}
}
// updata maxarea
for (int j = 0; j < n; j++) {
maxarea = Math.max(maxarea, (right[j] - left[j] + 1) * height[j]);
}
}
return maxarea;
}
}