zoukankan      html  css  js  c++  java
  • 单调栈——leetcode84柱状图中最大的矩形面积

    题目描述

    方法一——枚举

    • 枚举所有高度(矩形)
    • 当前矩形能围成的最大面积,取决于向左右扩展时,高度小于当前高度的矩形,记录下左右当前左右坐标,((right - left) -1)* heights[i] 就是当前矩形能围成的最大面积

    暴力枚举:枚举所有宽度,时间复杂度为O(n^2)

    	int largestRectangleArea(vector<int>& heights) {
    		int len = heights.size();
    		int ans = 0;
    		//枚举左边界
    		for(int i = 0;i < len;i++){
    			int minHeight = INT_MAX;
    			for(int j = i;j < len;j++){  //枚举右边界 
    				minHeight = min(minHeight,heights[j]); //高度取决于矮的一端
    				ans = max(ans, (j - i + 1) * minHeight);  //记录最大面积 
    			}
    		} 
    		return ans; 
    	}
    

    暴力枚举:枚举所有高度,时间复杂度O(n^2)

        int largestRectangleArea(vector<int>& heights){
    		int len = heights.size();
    		int ans = 0;
    		for(int i = 0;i < len;i++){
    		    int left = i;
    		    int right = i;
    		    int height = heights[i]; //固定高度
    			//向左扩展边界,找左边大于当前柱子高度并且最远的索引
    			while(left - 1 >= 0 && heights[left - 1] >= height){
    				left--; 
    			} 
    			
                //向右扩展边界,找右边大于当前柱子高度并且最远的索引
    			while(right + 1 < len && heights[right + 1] >= height){
    				right++;  
    			} 
    			
    			//计算当前高度可围成的最大面积
    			ans = max(ans,(right-left+1) * height);
    		} 
        	
        	return ans;
    	}
    

    方法二——分治法

    最大的矩形面积出现只会有以下三种情况

    • 高度最小的柱子能围成的最大面积
    • 最大面积出现在高度最小的柱子左边
    • 最大面积出现在高度最小的柱子右边
        int calculateArea(vector<int>& heights,int start,int end){
        	if(start > end){
        		return 0;
    		}
    		
    		int minWidth = heights[start];
    		
    		int cur = 0;
    		for(int i = start+1;i <= end;i++){
    			if(heights[i] < minWidth){
    				minWidth = heights[i];
    				cur = i;
    			}
    		}
    		
    		int AreaValue =  (end-start + 1) * minWidth;
    		int leftAreaValue = calculateArea(heights,start,cur-1);
    		int rightAreaValue = calculateArea(heights,cur+1,end);
    		return max(max(AreaValue,leftAreaValue),rightAreaValue);
    	}
    
        int largestRectangleArea(vector<int>& heights){
        	
        	return calculateArea(heights,0,heights.size()-1);
    	} 
    

    方法三——单调栈

    前面三种方法都超时,考虑优化时间复杂度。单调栈的解法与枚举高度类似,要使得当前高度能围成的矩形面积最大,需要向左右扩展能够到达的最大边界,因此我们需要维护一个单调递增的栈(栈中存放柱子的下标),当遍历到的柱子高度不满足单调递增时(大于栈顶柱子高度)说明它是栈顶柱子作为高度的右边界,左边界为栈顶元素的下一个元素,此时可以求出每个柱子作为高度时的最大面积,记录最大面积

    • 定义一个栈用于存放所有柱子的下标
    • 原数组首添0:便于计算左边界(避免对空栈处理),原数组末尾添0:使得栈中所有元素都能出栈(所有柱子高度能围成的最大面积都能求得)
    • 遍历数组,不满足单调递增时,说明栈顶柱子找到了右边界,栈顶柱子位置出栈,它的前一个位置(现在的栈顶元素就是它的左边界),计算宽度,右边界-左边界-1
    • 满足单调递增的柱子下标入栈
    • 直到遍历完柱子数组
    int largestRectangleArea(vector<int>& heights){
        int ans = 0;
        stack<int> st;
        heights.insert(heights.begin(), 0);  //减少栈空的判断
        heights.push_back(0);  //使得前面所有元素都能出栈
        for (int i = 0; i < heights.size(); i++){
            while (!st.empty() && heights[st.top()] > heights[i]){
                int cur = heights[st.top()]; //当前高度
                st.pop();
                ans = max(ans, (i - st.top() - 1) * cur);  //左边界:st.top() 右边界i 在计算宽度的时候需要减1
            }
            st.push(i);
        }
        return ans;
    }
    
    
  • 相关阅读:
    MySQL备份与恢复(5)mysqldump的关键参数说明
    MySQL备份与恢复(4)mysqldump备份表
    MySQL备份与恢复(3)mysqldump备份多个库
    MySQL备份与恢复(2)mysqldump多个命令参数
    MySQL备份与恢复(1)意义及重要性
    Redis(二)
    Redis(一)
    前端像素单位之间的区别
    Matplotlib
    解决问题:[Vue warn]: Error in beforeUpdate hook: "TypeError: Cannot read property 'setAttribute' of undefined"
  • 原文地址:https://www.cnblogs.com/Vicky1361/p/14696828.html
Copyright © 2011-2022 走看看