【Largest Rectangle in Histogram】cpp
题目:
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 height = [2,1,5,6,2,3]
,
return 10
.
代码:
class Solution { public: int largestRectangleArea(vector<int>& height) { int ret = 0; const size_t len = height.size(); if (!len) return len; int *dp_left = new int[len](), *dp_right = new int[len](); dp_left[0] = 0; dp_right[len-1] = len-1; // dp_left : record the left most position of height arr that the curr element can reach for ( size_t i = 1; i < len; ++i ){ int left = i; while ( left>0 && height[i]<=height[left-1] ) left = dp_left[left-1]; dp_left[i] = left; } // dp_right : vice versa for ( int i = len-2; i >0; --i) { int right = i; while ( right<len-1 && height[i]<=height[right+1] ) right = dp_right[right+1]; dp_right[i] = right; } // get the largest rectangle for ( size_t i = 0; i < len; ++i ) ret = std::max( ret, (dp_right[i]-dp_left[i]+1)*height[i] ); delete[] dp_left; delete[] dp_right; return ret; } };
tips:
采用dp的思路,主要参考 http://www.acmerblog.com/largest-rectangle-in-histogram-6117.html
遍历三次:
1. left to right : dp_left[i]数组存放height[i]向左最多能推到哪个位置
2. right to left : dp_right[i]数组存放height[i]向右最多能推到哪个位置
注意,不论是dp_left还是dp_right存放都是height数组的绝对位置(一开始dp_right一直存放相对位置,导致不能AC)
这里虽然for循环中又有while循环,但是复杂度并不是O(n²),原因并不是一个挨着一个跳的,而是用之前比较的结果(dp_left,dp_right)跳的。
3. 最后走一遍dp,记录最大值
==========================================
自己找虐,又去追了一下stack的解法。自己写了很久并没有通过,学习了下网上的代码。
class Solution { public: int largestRectangleArea(vector<int>& height) { int ret = 0; height.push_back(0); stack<int> sta; for ( int i = 0; i < height.size(); ) { if ( sta.empty() || height[i]>height[sta.top()] ) { sta.push(i++); } else { int tmp = sta.top(); sta.pop(); ret = std::max( ret, height[tmp]*(sta.empty() ? i:i-sta.top()-1 )); } } return ret; } };
核心思想就是:维护一个递增的stack。
1. 一旦遇到不能维持递增stack的元素了,就逐个往外弹出,直到能压进去。
2. 往外弹一个元素,就意味着这个元素不能再留着了,因此就计算一下包含弹出的这个元素在内,最大的rectangle是多少。
这里可能有一个疑问:把这个元素弹出来,那万一这个元素跟后面的元素能配上,获得更大大面积了呢?
这个是不可能发生的,因为这个元素能弹出来,必然是在其后面遇上了比它小的元素(阻断了被弹出的元素与后面的联系),因此这种算法是合理的。完毕。
===============================================
第二次过这道题,只记得用递增的stack来做了。
(1)stack里面存的是元素的下标
(2)先弹出来栈顶的元素,再看新的栈顶的元素(刚弹出来的这个元素往前能推到哪里)
class Solution { public: int largestRectangleArea(vector<int>& height) { if (height.size()==0) return 0; height.push_back(0); int ret = 0; stack<int> sta; for ( int i=0; i<height.size(); ++i ) { if ( sta.empty() || height[sta.top()]<height[i] ) { sta.push(i); } else { while ( !sta.empty() && height[sta.top()]>=height[i] ) { int tmp = sta.top(); sta.pop(); if ( sta.empty() ) { ret = max(ret, i*height[tmp]); } else { ret = max(ret, (i-sta.top()-1)*height[tmp]); } } sta.push(i); } } return ret; } };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?