-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
largestRectangleInHistogram.cpp
221 lines (203 loc) · 6.75 KB
/
largestRectangleInHistogram.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
// Source : https://oj.leetcode.com/problems/largest-rectangle-in-histogram/
// Author : Hao Chen
// Date : 2014-07-20
/**********************************************************************************
*
* 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.
*
* 6
* +---+
* 5 | |
* +---+ |
* | | |
* | | |
* | | | 3
* | | | +---+
* 2 | | | 2 | |
* +---+ | | +---+ |
* | | 1 | | | | |
* | +---+ | | | |
* | | | | | | |
* +---+---+---+---+---+---+
*
* Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
*
*
* 6
* +---+
* 5 | |
* +-------|
* |-------|
* |-------|
* |-------| 3
* |-------| +---+
* 2 |-------| 2 | |
* +---+ |-------|---+ |
* | | 1 |-------| | |
* | +---|-------| | |
* | | |-------| | |
* +---+---+---+---+---+---+
*
*
* 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.
*
*
**********************************************************************************/
#include <iostream>
#include <vector>
using namespace std;
//Time Limit Exceeded
int largestRectangleArea_01(vector<int>& heights) {
if (heights.size() == 0) return 0;
// idx of the first bar in the left or right that is lower than current bar
vector<int> left(heights.size());
vector<int> right(heights.size());
right[heights.size() - 1] = heights.size();
left[0] = -1;
for (int i = 1; i < heights.size(); i++) {
int l = i - 1;
while (l >= 0 && heights[l] >= heights[i]) {
l--;
}
left[i] = l;
}
for (int i = heights.size() - 2; i >= 0; i--) {
int r = i + 1;
while (r < heights.size() && heights[r] >= heights[i]) {
r++;
}
right[i] = r;
}
int maxArea = 0;
for (int i = 0; i < heights.size(); i++) {
maxArea = max(maxArea, heights[i] * (right[i] - left[i] - 1));
}
return maxArea;
}
// As we know, the area = width * height
// For every bar, the 'height' is determined by the loweset bar.
//
// 1) We traverse all bars from left to right, maintain a stack of bars. Every bar is pushed to stack once.
// 2) A bar is popped from stack when a bar of smaller height is seen.
// 3) When a bar is popped, we calculate the area with the popped bar as smallest bar.
// 4) How do we get left and right indexes of the popped bar –
// the current index tells us the ‘right index’ and index of previous item in stack is the ‘left index’.
//
//
// In other word, the stack only stores the incresing bars, let's see some example
//
// Example 1
// ---------
// height = [1,2,3,4]
//
// stack[] = [ 0, 1, 2, 3 ], i=4
//
// 1) pop 3, area = height[3] * 1 = 4
// 2) pop 2, area = height[2] * 2 = 4
// 3) pop 1, area = height[1] * 3 = 6
// 4) pop 0, area = height[0] * 4 = 4
//
//
// Example 2
// ---------
// height = [2,1,2]
//
// stack[] = [ 0 ], i=1
// 1) pop 0, area = height[0] * 1 = 2
//
// stack[] = [ 1,2 ], i=3, meet the end
// 1) pop 2, area = height[2] * 1 = 2
// 2) pop 1, area = height[1] * 3 = 3
//
//
// Example 3
// ---------
// height = [4,2,0,3,2,5]
//
// stack[] = [ 0 ], i=1, height[1] goes down
// 1) pop 0, area = height[0] * 1 = 4
//
// stack[] = [ 1 ], i=2, height[2] goes down
// 1) pop 1, area = height[1] * 2 = 4 // <- how do we know the left?
// start from the 0 ??
//
// stack[] = [ 2, 3 ], i=4, height[4] goes down
// 1) pop 3, area = height[3] * 1 = 3
// 2) pop 2, area = height[2] * ? = 0 // <- how do we know the left?
// start from the 0 ??
//
// stack[] = [ 2,4,5 ], i=6, meet the end
// 1) pop 5, area = height[5] * 1 = 5
// 2) pop 4, area = height[4] * 3 = 6 // <- how do we know the left?
// need check the previous item.
// 3) pop 2, area = height[2] * ? = 4 // <- how do we know the left?
// start from the 0 ??
//
// so, we can see, when the stack pop the top, the area formular is
//
// height[stack_pop] * i - stack[current_top] - 1, if stack is not empty
// height[stack_pop] * i, if stack is empty
//
int largestRectangleArea(vector<int> &height) {
if (height.size()<=0) return 0;
//Create an empty stack.
vector<int> stack;
//add a flag as a trigger if the end bar is met, and need to check the stack is empty of not .
height.push_back(0);
int maxArea = 0;
for(int i=0; i<height.size(); i++){
//If stack is empty or height[i] is higher than the bar at top of stack, then push ‘i’ to stack.
if ( stack.size()<=0 || height[i] >= height[stack.back()] ) {
stack.push_back(i);
continue;
}
//If this bar is smaller than the top of stack, then keep removing the top of stack while top of the stack is greater.
//Let the removed bar be height[top]. Calculate area of rectangle with height[top] as smallest bar.
//For height[top], the ‘left index’ is previous (previous to top) item in stack and ‘right index’ is ‘i’ (current index).
int topIdx = stack.back();
stack.pop_back();
int area = height[topIdx] * (stack.size()==0 ? i : i - stack.back() - 1 );
if ( area > maxArea ) {
maxArea = area;
}
//one more time. Because the stack might still have item.
i--;
}
return maxArea;
}
void printArray(vector<int> &v)
{
cout << "{";
for(int i=0; i<v.size(); i++) {
cout << " " << v[i];
}
cout << "}" << endl;
}
void test(int a[], int n)
{
vector<int> v(a, a + n);
printArray(v);
cout << largestRectangleArea(v) << endl;
}
int main()
{
#define TEST(a) test(a, sizeof(a)/sizeof(int))
int a0[] = {2,1,3,1};
TEST(a0);
int a1[] = {2,1,5,6,2,3};
TEST(a1);
return 0;
}
/*int main()
{
int a[] = {2,1,5,6,2,3};
vector<int> v(a, a + sizeof(a)/sizeof(int));
printArray(v);
cout << largestRectangleArea(v) << endl;
return 0;
}*/