forked from pezy/LeetCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added 114. Largest Rectangle in Histogram
- Loading branch information
Showing
3 changed files
with
91 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
|
||
_ _ | ||
| | _ _ | | | ||
| | | |_| | | | | ||
| | |*|*|*| | | | ||
| |_|*|*|*| | | | ||
| | |*|*|*|_| | | ||
|_|_|_|_|_|_|_| | ||
6 2 5 4 5 1 6 | ||
^ ^ ^ | ||
0 1 2 3 4 5 6 | ||
|
||
如图所示,很直观:`3 * 4 == 12`.首先思考,我们是如何得到最大面积 12 的? | ||
|
||
我们发现,要计算 Largest Rectangle ,关键是找**短板**,如我们挑选的 4,类似的还有哪些呢?列个表: | ||
|
||
|min_height|rectangle|area| | ||
|:--------:|:-------:|:--:| | ||
| 2 | 0 -> 4 | 2*5| | ||
| 4 | 2 -> 4 | 4*3| | ||
| 1 | 0 -> 6 | 1*6| | ||
|
||
最终很明显,area 最大的即为中间那行,结果为 12. | ||
|
||
再进一步思考: | ||
|
||
1. 短板是如何摘出来的?这个很显然,是衰减发生的时候出现的。如 6->2, 5->4, 5->1. | ||
2. 短板的周期如何得出?细致观察后,发现是短板之间的升降分割出的。如 2->4:(2), 2->1, 4->1:(4), 2 和 4 便是分隔符。 | ||
|
||
好了,现在发现了规律,但如何准确找到所需的数据结构呢? | ||
|
||
我们的第一个目的显然是要找出短板,短板的条件是: | ||
|
||
height[i] < height[i-1] | ||
|
||
貌似迭代一遍即可,但短板的周期分隔点如何得出呢?我们不仅要找出短板,还需要留下短板以及短板的 index, 以便寻找分隔符。 | ||
|
||
看来我们需要一把筛子,筛掉不符合短板条件的,留下短板。 | ||
|
||
**栈**非常符合筛子的特性,不管三七二十一,push 进去,不符合则 pop 出来。 | ||
|
||
```cpp | ||
int max_area = 0, i = 0, size = height.size(); | ||
for (stack<int> stk; i<size || !stk.empty(); ) { // 这个的 for 循环在二叉树的题目里经常出现(DFS) | ||
if (stk.empty() || (i != size && height[stk.top()] <= height[i])) stk.push(i++); // 不是短板,则 push | ||
else { | ||
int tp = stk.top(); stk.pop(); | ||
max_area = std::max(max_area, height[tp] * (stk.empty() ? i : i-stk.top()-1)); | ||
} | ||
} | ||
``` | ||
|
||
基本逻辑很简单,5 行结束。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#define CATCH_CONFIG_MAIN | ||
#include "../Catch/single_include/catch.hpp" | ||
#include "solution.h" | ||
|
||
TEST_CASE("Largest Rectangle in Histogram", "[largestRectangleArea]") | ||
{ | ||
Solution s; | ||
SECTION( "common1" ) | ||
{ | ||
std::vector<int> height{6, 2, 5, 4, 5, 1, 6}; | ||
REQUIRE( s.largestRectangleArea(height) == 12 ); | ||
} | ||
SECTION( "common2" ) | ||
{ | ||
std::vector<int> height{2, 1, 5, 6, 2, 3}; | ||
REQUIRE( s.largestRectangleArea(height) == 10 ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#include <vector> | ||
using std::vector; | ||
#include <stack> | ||
using std::stack; | ||
#include <algorithm> | ||
using std::max; | ||
|
||
class Solution { | ||
public: | ||
int largestRectangleArea(vector<int> &height) { | ||
int max_area = 0, i = 0, size = height.size(); | ||
for (stack<int> stk; i<size || !stk.empty(); ) | ||
if (stk.empty() || (i != size && height[stk.top()] <= height[i])) stk.push(i++); | ||
else { | ||
int tp = stk.top(); stk.pop(); | ||
max_area = max(max_area, height[tp] * (stk.empty() ? i : i-stk.top()-1)); | ||
} | ||
return max_area; | ||
} | ||
}; |