85 Maximal Rectangle
问题:找到矩形内连续的都是1,这个矩形的面积。首先考虑到的是暴力搜索,不断枚举起始节点的x,y坐标,节点节点的x,y坐标。计算矩形面积的几个方法:1 一个一个元素遍历;2 利用矩阵长*宽;3 利用上一步计算的矩形的值。这个需要4层循环,慢。
学习:讨论里面有一种动态规划的解法。虽然看了,也知道怎么回事,但是还想不明白作者是如何相出这种DP想法的。我应该再复习DP的思想。
/*** 动态规划的思想* 来自https://leetcode.com/problems/maximal-rectangle/discuss/29054* area[i][j]= [right(i,j) - left(i,j)]*height(i,j).* left(i,j) = max(left(i-1,j), cur_left),cur_left can be determined from the current row* right(i,j) = min(right(i-1,j), cur_right), cur_right can be determined from the current row* height(i,j) = height(i-1,j) + 1, if matrix[i][j]==‘1’;* height(i,j) = 0, if matrix[i][j]==‘0’* @param matrix* @return*/public int maximalRectangleV2(char[][] matrix) {int m = matrix.length;if (m == 0)return 0;int n = matrix[0].length;int[] left = new int[n], right = new int[n], height = new int[n];for(int i=0;i<n;i++){right[i] = n;}int maxA = 0;for (int i = 0; i < m; i++) {int cur_left = 0, cur_right = n;for (int j = 0; j < n; j++) { // compute height (can do this from either side)if (matrix[i][j] == '1')height[j]++;elseheight[j] = 0;}for (int j = 0; j < n; j++) { // compute left (from left to right)if (matrix[i][j] == '1')left[j] = Math.max(left[j], cur_left);else {left[j] = 0;cur_left = j + 1;}}// compute right (from right to left)for (int j = n - 1; j >= 0; j--) {if (matrix[i][j] == '1')right[j] = Math.min(right[j], cur_right);else {right[j] = n;cur_right = j;}}// compute the area of rectangle (can do this from either side)for (int j = 0; j < n; j++)maxA = Math.max(maxA, (right[j] - left[j]) * height[j]);}return maxA;}
84 Largest Rectangle in Histogram
问题:本题解题思路一开始是想下标从0开始,如果使用heights[0],最大面积是多少;如果使用 heights[0],heights[1]得到的举行,最大面积是多少;例如当计算完(2,1,5)这前三个bar的最大矩形面积,再计算(2,1,5,6)这四个bar的矩形面积。这其实是一种动态规划的思想。但是这个递推式是写不出来的。
学习:应该使用的思路是全局。还是下标从0开始,当整个矩形的高度是heights[0]的时候,最大面积是多少;当整个矩形的高度是heights[1]的时候,最大矩形面积是多少。 如果这样想,对于某一个特定的高度heights[i],最大的矩形面积是(heights[i]*(rights[i]-lefts[i]+1))。rights[i]就是heigths[i]的高度能达到的最右边的下标。 lefts[i]=是heights[i]能达到的最左边的下标。
下面的代码在实现过程中做了一点变化。lessFromLeft[i] = 比i小,最靠近i的 && 使得heights[lessFromLeft[i]]< heights[i] lessFromRight[i] = 比i大,最靠近i的 && 使得heights[lessFromRight[i]]
public int largestRectangleArea(int[] heights) {int n = heights.length;if(n==0) return 0;int[] lessFromLeft = new int[n];//对于下标i,从左边开始,最靠近i的idx使得heights[lessFromLeft[i]]< heights[i]int[] lessFromRight = new int[n];//对于下标i,从右边开始数,最靠近i的idx使得heights[lessFromRight[i]]<heights[i]int ans = 0;lessFromLeft[0] = -1;//边界值处理for (int i = 1; i < n; i++) {int p = i - 1;while (p >= 0 && heights[p] >= heights[i]) {p = lessFromLeft[p];}lessFromLeft[i] = p;}lessFromRight[n - 1] = n;for (int i = n - 2; i >= 0; i--) {int p = i +1;while(p < n && heights[p]>=heights[i]){p = lessFromRight[p];}lessFromRight[i] = p;}for(int i=0;i<n;i++){ans = Math.max(ans, (lessFromRight[i] - lessFromLeft[i]-1)*heights[i]);}return ans;}