leecode 解题总结:84. Largest Rectangle in Histogram

来源:互联网 发布:mendelow矩阵分析 编辑:程序博客网 时间:2024/04/28 18:15
#include <iostream>#include <stdio.h>#include <vector>#include <set>#include <stack>using namespace std;/*问题:Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].The largest rectangle is shown in the shaded area, which has area = 10 unit.For example,Given heights = [2,1,5,6,2,3],return 10.分析:这道题目需要从矩阵图中找到面积最大的矩阵,矩阵条的高度等于数组中给定值的高度。暴力破解:遍历每个bar,然后遍历高度1~h,对每个高度从当前一直到最后一个bar。或者简单一点,罗列出每个起始bar和终止bar,然后设定高度为从起始bar到终止bar中高度的最小值时间复杂度为O(n^2)。因为从一组数里选择最小的数时间复杂度为O(n)或者O(logN)用小丁对但是不一定[low,high]的面积=(high-low+1)*minHeight,可能会是其他。是否可以选定一个中心,然后向两边扩散。如果中心的左边>右边,那么应该优先选择哪一边有点累似盛水的题目,盛水从左和从右分别维持两个指针,和leftMax,rightMax,如果leftMax < rightMax,以左边为基准。未能解答出。网上解法:从左导游遍历所有bar,每个bar仅雅茹到栈一次。一个bar会被弹出,当前遇到一个较小高度的bar。当一个bar被弹出时,我们计算弹出的bar的面积并作为最小的bar。如何获取弹出bar左边和右边的下标?当前的下标告诉了我们右边的下标,而在栈中存储的前一个bar就是左边的下标。步骤:1】创建空栈,设直方图为hists[i],i从0到n-1。2】如果栈为空,或者当前hists[i]>=栈顶高度,就压入i   否则,如果hists[i] < 栈顶对应元素高度,就移出栈顶,直到栈顶元素高度<=hist[i],   在此过程中不断计算面积,该面积是所有大于hists[i]的连续bar组成的矩阵面积输入:6(数组元素个数)2 1 5 6 2 376 2 5 4 5 1 6输出:1012关键:1 核心思想是:维护一个单调非递减的区间[low,high],而栈stack中存放了非递减区间的元素下标,一旦找到当前元素(对应下标为i)<栈顶元素,则开始计算面积面积 = 当前高度 * (终点 - 起点 + 1),满足:终点对应元素高度>=当前高度,起点对应元素高度>=当前高度由于是单调非递减区间弹出一次栈顶,新的栈顶对应元素高度<=当前高度,那么新的栈顶记录的位置+1 对应元素高度 >= 当前高度【关键】所以起点 = 新的栈顶记录的位置 + 1终点 = i - 1面积 = 当前高度 * (i - 1  - (新的栈顶记录的位置+1) + 1) = 当前高度 * ( i - 1 - 新的栈顶记录的位置) //首先明确hists中存放了单调非递减区间对应高度的下标,所以heights[删除栈顶后的新top] <= heights[top]while(i < n){//当前元素高度>=栈顶元素高度,压入栈中。为的是寻找递增区间if(hists.empty() || heights.at(i) >= heights[hists.top()] ){hists.push(i++);}//当前元素高度< 栈顶元素高度,开始计算最大面积else{top = hists.top();//top是当前递增区间终止bar的下标,用于计算高度hists.pop();//这里之所以要弹出,是因为//宽度=i-1(递增高度最大值对应下标) - 弹出当前元素后的栈顶高度if(hists.empty()){width = i;//表明0~i-1都是递增区间,长度为i}else{//这样理解i是第一个小于递增区间的下标。 i-1是递增区间的终止下标,那么hists.top()+1对应的是大于等于当前元素高度的起始结点下标//宽度=终点-起点+1=i-1 - (hists.top() + 1) + 1 = i - 1 - hists.top()width = i - 1 - hists.top();}area = heights.at(top) * width;//注意对应高度是top下标对应高度if(area > maxArea){maxArea = area;}}}*/class Solution {public:    int largestRectangleArea(vector<int>& heights) {        if(heights.empty()){return 0;}stack<int> hists;int i = 0 ; int n = heights.size();int area;int maxArea = INT_MIN;int top;int width;//首先明确hists中存放了单调非递减区间对应高度的下标,所以heights[删除栈顶后的新top] <= heights[top]while(i < n){//当前元素高度>=栈顶元素高度,压入栈中。为的是寻找递增区间if(hists.empty() || heights.at(i) >= heights[hists.top()] ){hists.push(i++);}//当前元素高度< 栈顶元素高度,开始计算最大面积else{top = hists.top();//top是当前递增区间终止bar的下标,用于计算高度hists.pop();//这里之所以要弹出,是因为//宽度=i-1(递增高度最大值对应下标) - 弹出当前元素后的栈顶高度if(hists.empty()){width = i;//表明0~i-1都是递增区间,长度为i}else{//这样理解i是第一个小于递增区间的下标。 i-1是递增区间的终止下标,那么hists.top()+1对应的是大于等于当前元素高度的起始结点下标//宽度=终点-起点+1=i-1 - (hists.top() + 1) + 1 = i - 1 - hists.top()width = i - 1 - hists.top();}area = heights.at(top) * width;//注意对应高度是top下标对应高度if(area > maxArea){maxArea = area;}}}//如果最后还有元素留在栈中,也必定是升序的,再计算一次while(!hists.empty()){top = hists.top();hists.pop();if(hists.empty()){width = i;}else{width = i - 1 - hists.top();}area = heights.at(top) * width;if(area > maxArea){maxArea = area;}}return maxArea;}//从数组中选择最大的数,如果用线性时间选择,选择的是前k个数,时间复杂度为O(logN)//或者用堆来做,堆的实现应该是set,但是set你得先插入一遍数据,和直接遍历找出最小的一样。    int largestRectangleArea2(vector<int>& heights) {        if(heights.empty()){return 0;}int size = heights.size();int maxArea = INT_MIN;int minHeight = INT_MAX;int area;int beg = -1;int end = -1;//最后一个位置i能够取到for(int i = 0 ; i < size  ; i++){for(int j = i ; j < size ; j++){minHeight = INT_MAX;for(int k = i ; k <= j; k++){//求出最小高度if(heights.at(k) < minHeight){minHeight = heights.at(k);}}//求出面积area = minHeight * (j - i + 1);if(area > maxArea){maxArea = area;beg = i;end = j;}}}return maxArea;    }};void print(vector<int>& result){if(result.empty()){cout << "no result" << endl;return;}int size = result.size();for(int i = 0 ; i < size ; i++){cout << result.at(i) << " " ;}cout << endl;}void process(){ vector<int> nums; int value; int num; Solution solution; vector<int> result; while(cin >> num ) { nums.clear(); for(int i = 0 ; i < num ; i++) { cin >> value; nums.push_back(value); } int result = solution.largestRectangleArea(nums); cout << result << endl; }}int main(int argc , char* argv[]){process();getchar();return 0;}

0 0
原创粉丝点击