@@ -281,52 +281,137 @@ class Solution {
281
281
282
282
Python:
283
283
284
- 动态规划
285
284
``` python3
285
+
286
+ # 双指针;暴力解法(leetcode超时)
286
287
class Solution :
287
288
def largestRectangleArea (self , heights : List[int ]) -> int :
289
+ # 从左向右遍历:以每一根柱子为主心骨(当前轮最高的参照物),迭代直到找到左侧和右侧各第一个矮一级的柱子
290
+ res = 0
291
+
292
+ for i in range (len (heights)):
293
+ left = i
294
+ right = i
295
+ # 向左侧遍历:寻找第一个矮一级的柱子
296
+ for _ in range (left, - 1 , - 1 ):
297
+ if heights[left] < heights[i]:
298
+ break
299
+ left -= 1
300
+ # 向右侧遍历:寻找第一个矮一级的柱子
301
+ for _ in range (right, len (heights)):
302
+ if heights[right] < heights[i]:
303
+ break
304
+ right += 1
305
+
306
+ width = right - left - 1
307
+ height = heights[i]
308
+ res = max (res, width * height)
309
+
310
+ return res
311
+
312
+ # DP动态规划
313
+ class Solution :
314
+ def largestRectangleArea (self , heights : List[int ]) -> int :
315
+ size = len (heights)
316
+ # 两个DP数列储存的均是下标index
317
+ min_left_index = [0 ] * size
318
+ min_right_index = [0 ] * size
288
319
result = 0
289
- minleftindex, minrightindex = [0 ]* len (heights), [0 ]* len (heights)
320
+
321
+ # 记录每个柱子的左侧第一个矮一级的柱子的下标
322
+ min_left_index[0 ] = - 1 # 初始化防止while死循环
323
+ for i in range (1 , size):
324
+ # 以当前柱子为主心骨,向左迭代寻找次级柱子
325
+ temp = i - 1
326
+ while temp >= 0 and heights[temp] >= heights[i]:
327
+ # 当左侧的柱子持续较高时,尝试这个高柱子自己的次级柱子(DP
328
+ temp = min_left_index[temp]
329
+ # 当找到左侧矮一级的目标柱子时
330
+ min_left_index[i] = temp
290
331
291
- minleftindex[0 ]= - 1
292
- for i in range (1 ,len (heights)):
293
- t = i- 1
294
- while t>= 0 and heights[t]>= heights[i]: t= minleftindex[t]
295
- minleftindex[i]= t
296
-
297
- minrightindex[- 1 ]= len (heights)
298
- for i in range (len (heights)- 2 ,- 1 ,- 1 ):
299
- t= i+ 1
300
- while t< len (heights) and heights[t]>= heights[i]: t= minrightindex[t]
301
- minrightindex[i]= t
332
+ # 记录每个柱子的右侧第一个矮一级的柱子的下标
333
+ min_right_index[size- 1 ] = size # 初始化防止while死循环
334
+ for i in range (size- 2 , - 1 , - 1 ):
335
+ # 以当前柱子为主心骨,向右迭代寻找次级柱子
336
+ temp = i + 1
337
+ while temp < size and heights[temp] >= heights[i]:
338
+ # 当右侧的柱子持续较高时,尝试这个高柱子自己的次级柱子(DP
339
+ temp = min_right_index[temp]
340
+ # 当找到右侧矮一级的目标柱子时
341
+ min_right_index[i] = temp
342
+
343
+ for i in range (size):
344
+ area = heights[i] * (min_right_index[i] - min_left_index[i] - 1 )
345
+ result = max (area, result)
302
346
303
- for i in range (0 ,len (heights)):
304
- left = minleftindex[i]
305
- right = minrightindex[i]
306
- summ = (right- left- 1 )* heights[i]
307
- result = max (result,summ)
308
347
return result
309
- ```
310
- 单调栈 版本二
311
- ``` python3
348
+
349
+ # 单调栈
312
350
class Solution :
313
351
def largestRectangleArea (self , heights : List[int ]) -> int :
314
- heights.insert(0 ,0 ) # 数组头部加入元素0
315
- heights.append(0 ) # 数组尾部加入元素0
316
- st = [0 ]
352
+ # Monotonic Stack
353
+ '''
354
+ 找每个柱子左右侧的第一个高度值小于该柱子的柱子
355
+ 单调栈:栈顶到栈底:从大到小(每插入一个新的小数值时,都要弹出先前的大数值)
356
+ 栈顶,栈顶的下一个元素,即将入栈的元素:这三个元素组成了最大面积的高度和宽度
357
+ 情况一:当前遍历的元素heights[i]大于栈顶元素的情况
358
+ 情况二:当前遍历的元素heights[i]等于栈顶元素的情况
359
+ 情况三:当前遍历的元素heights[i]小于栈顶元素的情况
360
+ '''
361
+
362
+ # 输入数组首尾各补上一个0(与42.接雨水不同的是,本题原首尾的两个柱子可以作为核心柱进行最大面积尝试
363
+ heights.insert(0 , 0 )
364
+ heights.append(0 )
365
+ stack = [0 ]
317
366
result = 0
318
- for i in range (1 ,len (heights)):
319
- while st!= [] and heights[i]< heights[st[- 1 ]]:
320
- midh = heights[st[- 1 ]]
321
- st.pop()
322
- if st!= []:
323
- minrightindex = i
324
- minleftindex = st[- 1 ]
325
- summ = (minrightindex- minleftindex- 1 )* midh
326
- result = max (summ,result)
327
- st.append(i)
367
+ for i in range (1 , len (heights)):
368
+ # 情况一
369
+ if heights[i] > heights[stack[- 1 ]]:
370
+ stack.append(i)
371
+ # 情况二
372
+ elif heights[i] == heights[stack[- 1 ]]:
373
+ stack.pop()
374
+ stack.append(i)
375
+ # 情况三
376
+ else :
377
+ # 抛出所有较高的柱子
378
+ while stack and heights[i] < heights[stack[- 1 ]]:
379
+ # 栈顶就是中间的柱子,主心骨
380
+ mid_index = stack[- 1 ]
381
+ stack.pop()
382
+ if stack:
383
+ left_index = stack[- 1 ]
384
+ right_index = i
385
+ width = right_index - left_index - 1
386
+ height = heights[mid_index]
387
+ result = max (result, width * height)
388
+ stack.append(i)
328
389
return result
390
+
391
+ # 单调栈精简
392
+ class Solution :
393
+ def largestRectangleArea (self , heights : List[int ]) -> int :
394
+ heights.insert(0 , 0 )
395
+ heights.append(0 )
396
+ stack = [0 ]
397
+ result = 0
398
+ for i in range (1 , len (heights)):
399
+ while stack and heights[i] < heights[stack[- 1 ]]:
400
+ mid_height = heights[stack[- 1 ]]
401
+ stack.pop()
402
+ if stack:
403
+ # area = width * height
404
+ area = (i - stack[- 1 ] - 1 ) * mid_height
405
+ result = max (area, result)
406
+ stack.append(i)
407
+ return result
408
+
409
+
410
+
411
+
412
+
329
413
```
414
+ *****
330
415
331
416
JavaScript:
332
417
``` javascript
0 commit comments