This commit is contained in:
programmercarl
2023-02-22 17:21:40 +08:00
parent 1aeb1dfe2d
commit 97e495cccc
4 changed files with 63 additions and 31 deletions

View File

@@ -17,6 +17,8 @@
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210803220506.png)
* 1 <= heights.length <=10^5
* 0 <= heights[i] <= 10^4
# 思路
@@ -24,9 +26,9 @@
其实这两道题目先做那一道都可以但我先写的42.接雨水的题解,所以如果没做过接雨水的话,建议先做一做接雨水,可以参考我的题解:[42. 接雨水](https://programmercarl.com/0042.接雨水.html)
我们先来看一下双指针的解法:
我们先来看一下暴力解法的解法:
## 双指针解法
## 暴力解法
```CPP
class Solution {
@@ -53,9 +55,9 @@ public:
如上代码并不能通过leetcode超时了因为时间复杂度是$O(n^2)$。
## 动态规划
## 双指针解法
本题动态规划的写法整体思路和[42. 接雨水](https://programmercarl.com/0042.接雨水.html)是一致的,但要比[42. 接雨水](https://programmercarl.com/0042.接雨水.html)难一些。
本题双指针的写法整体思路和[42. 接雨水](https://programmercarl.com/0042.接雨水.html)是一致的,但要比[42. 接雨水](https://programmercarl.com/0042.接雨水.html)难一些。
难就难在本题要记录记录每个柱子 左边第一个小于该柱子的下标,而不是左边第一个小于该柱子的高度。
@@ -110,7 +112,7 @@ public:
我来举一个例子,如图:
![84.柱状图中最大的矩形](https://img-blog.csdnimg.cn/20210223155303971.jpg)
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20230221165730.png)
只有栈里从大到小的顺序,才能保证栈顶元素找到左右两边第一个小于栈顶元素的柱子。
@@ -122,11 +124,11 @@ public:
除了栈内元素顺序和接雨水不同,剩下的逻辑就都差不多了,在题解[42. 接雨水](https://programmercarl.com/0042.接雨水.html)我已经对单调栈的各个方面做了详细讲解,这里就不赘述了。
剩下就是分析清楚如下三种情况:
主要就是分析清楚如下三种情况:
* 情况一当前遍历的元素heights[i]于栈顶元素heights[st.top()]的情况
* 情况一当前遍历的元素heights[i]于栈顶元素heights[st.top()]的情况
* 情况二当前遍历的元素heights[i]等于栈顶元素heights[st.top()]的情况
* 情况三当前遍历的元素heights[i]于栈顶元素heights[st.top()]的情况
* 情况三当前遍历的元素heights[i]于栈顶元素heights[st.top()]的情况
C++代码如下:
@@ -135,28 +137,30 @@ C++代码如下:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int result = 0;
stack<int> st;
heights.insert(heights.begin(), 0); // 数组头部加入元素0
heights.push_back(0); // 数组尾部加入元素0
st.push(0);
int result = 0;
// 第一个元素已经入栈从下标1开始
for (int i = 1; i < heights.size(); i++) {
// 注意heights[i] 是和heights[st.top()] 比较 st.top()是下标
if (heights[i] > heights[st.top()]) {
if (heights[i] > heights[st.top()]) { // 情况一
st.push(i);
} else if (heights[i] == heights[st.top()]) {
} else if (heights[i] == heights[st.top()]) { // 情况二
st.pop(); // 这个可以加,可以不加,效果一样,思路不同
st.push(i);
} else {
while (heights[i] < heights[st.top()]) { // 注意是while
} else { // 情况三
while (!st.empty() && heights[i] < heights[st.top()]) { // 注意是while
int mid = st.top();
st.pop();
int left = st.top();
int right = i;
int w = right - left - 1;
int h = heights[mid];
result = max(result, w * h);
if (!st.empty()) {
int left = st.top();
int right = i;
int w = right - left - 1;
int h = heights[mid];
result = max(result, w * h);
}
}
st.push(i);
}
@@ -165,9 +169,36 @@ public:
}
};
```
```
代码精简之后:
height数组上后0
0
[2,4,6,8] 0
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20230221163936.png)
0
0
[8,6,4,2] 8 6 8 mid8rigt6 left
midleftright
8
6 8 4 8 resutl就是0
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20230221164533.png)
height数组前后各加一个元素0
```CPP
// 版本二
@@ -200,7 +231,7 @@ public:
Java:
动态规划
暴力解法:
```java
class Solution {
public int largestRectangleArea(int[] heights) {
@@ -233,7 +264,7 @@ class Solution {
}
```
单调栈
单调栈:
```java
class Solution {
int largestRectangleArea(int[] heights) {
@@ -281,7 +312,7 @@ Python3:
```python
# 双指针;暴力解法leetcode超时
# 暴力解法leetcode超时
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
# 从左向右遍历:以每一根柱子为主心骨(当前轮最高的参照物),迭代直到找到左侧和右侧各第一个矮一级的柱子
@@ -307,7 +338,7 @@ class Solution:
return res
# DP动态规划
# 双指针
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
size = len(heights)
@@ -450,7 +481,7 @@ func largestRectangleArea(heights []int) int {
JavaScript:
```javascript
//动态规划 js中运行速度最快
//双指针 js中运行速度最快
var largestRectangleArea = function(heights) {
const len = heights.length;
const minLeftIndex = new Array(len);
@@ -525,7 +556,7 @@ var largestRectangleArea = function(heights) {
```
TypeScript
> 双指针法(会超时):
> 暴力法(会超时):
```typescript
function largestRectangleArea(heights: number[]): number {
@@ -546,7 +577,7 @@ function largestRectangleArea(heights: number[]): number {
};
```
> 动态规划预处理:
> 双指针预处理:
```typescript
function largestRectangleArea(heights: number[]): number {