84. 히스토그램에서 가장 큰 직사각형:
주어진 n 음수가 아닌 정수는 히스토그램의 각 열 높이를 나타내는 데 사용됩니다. 각 열은 서로 인접해 있으며 너비는 1 입니다.
이 히스토그램에서 그릴 수 있는 직사각형의 최대 면적을 구하십시오.
예시 1:
输入:
heights = [2,1,5,6,2,3]
输出:
10
解释:
最大的矩形为图中红色区域,面积为 10
예시 2:
输入:
heights = [2,4]
输出:
4
힌트:
- 1 5
- 0 <= 높이[i] <= 104
분석하다:
- 이 알고리즘 질문에 직면한 두 번째 마스터는 다시 한 번 깊은 생각에 빠졌습니다.
- 언뜻 보면 아이디어가 있는 것 같지만, 일단 막상 시작하면 어디서부터 시작해야 할지 막막하기 쉽습니다.
- 이중 루프를 수행하여 각 열을 순회하여 왼쪽에서 자신보다 낮은 첫 번째 열과 오른쪽에서 자신보다 낮은 첫 번째 열을 찾습니다. 이 방법으로 현재 열 높이의 최대 너비를 계산할 수 있습니다. .. 단서가 있다면 분명히 매우 그럴 것입니다. 잠깐, 더 좋은 방법이 있을까요?
- 각 열(자신보다 낮은 첫 번째 열)의 왼쪽 및 오른쪽 경계를 찾는 것이 핵심입니다. 검색 복잡도를 줄일 수 있는 방법이 있나요?
- 한 번의 순회에서 왼쪽과 오른쪽 경계를 찾을 수 있다면 좋을 것입니다. 아티팩트 단조 스택을 사용합니다. 스택이 비어 있으면 스택에 푸시합니다(여기서 기술을 사용하여 처리 논리를 통합할 수 있습니다). 그렇지 않으면 판단합니다. 다음 기둥이 스택의 상단보다 높거나 스택의 상단과 같은지 여부 스택의 상단이 동일한 높이이면 스택으로 직접 푸시됩니다. 스택의 경우 현재 열이 스택 맨 위 요소의 오른쪽 경계이므로 스택에서 팝됩니다. 이 과정을 반복하면 한 번의 순회로 왼쪽 및 오른쪽 경계를 찾을 수 있습니다.
- 순회 과정에서 스택이 비어 있는 상황, 모든 열을 순회했지만 스택이 비어 있지 않은 상황에 특히 주의하세요.
답변:
녹:
impl Solution {
pub fn largest_rectangle_area(heights: Vec<i32>) -> i32 {
let mut ans = 0;
let mut stack = vec![-1];
let n = heights.len();
(0..n).for_each(|i| {
while stack.len() > 1 && heights[*stack.last().unwrap() as usize] > heights[i] {
// 栈中比当前位置高的那些待确定右边界的下标都可以确定右边界了
ans = ans.max(heights[stack.pop().unwrap() as usize] * (i as i32 - 1 - stack.last().unwrap()));
}
// 入栈,等到能够确定右边界时处理
stack.push(i as i32);
});
while stack.len() > 1 {
// 栈中剩余的都是右边没有更低的
ans = ans.max(heights[stack.pop().unwrap() as usize] * (n as i32 - 1 - stack.last().unwrap()));
}
return ans;
}
}
가다:
func largestRectangleArea(heights []int) int {
max := func(x, y int) int {
if x > y {
return x
}
return y
}
ans := 0
n := len(heights)
stack := []int{
-1}
for i := 0; i < n; i++ {
for len(stack) > 1 && heights[stack[len(stack)-1]] > heights[i] {
// 栈中比当前位置高的那些待确定右边界的下标都可以确定右边界了
ans = max(ans, heights[stack[len(stack)-1]]*(i-1-stack[len(stack)-2]))
// 出栈
stack = stack[:len(stack)-1]
}
// 入栈,等到能够确定右边界时处理
stack = append(stack, i)
}
for len(stack) > 1 {
// 栈中剩余的都是右边没有更低的
ans = max(ans, heights[stack[len(stack)-1]]*(n-1-stack[len(stack)-2]))
// 出栈
stack = stack[:len(stack)-1]
}
return ans
}
C++:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int ans = 0;
const int n = heights.size();
stack<int> s;
s.push(-1);
for (int i = 0; i < n; ++i) {
while (s.size() > 1 && heights[s.top()] > heights[i]) {
// 栈中比当前位置高的那些待确定右边界的下标都可以确定右边界了
int height = heights[s.top()];
s.pop();
ans = max(ans, height * (i - 1 - s.top()));
}
// 入栈,等到能够确定右边界时处理
s.push(i);
}
while (s.size() > 1) {
// 栈中剩余的都是右边没有更低的
int height = heights[s.top()];
s.pop();
ans = max(ans, height * (n - 1 - s.top()));
}
return ans;
}
};
파이썬:
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
ans = 0
n = len(heights)
stack = [-1]
for i in range(n):
while len(stack) > 1 and heights[stack[-1]] > heights[i]:
# 比当前位置高的那些待确定右边界的下标都可以确定右边界了
ans = max(ans, heights[stack.pop()] * (i - 1 - stack[-1]))
# 入栈,等到能够确定右边界时处理
stack.append(i)
while len(stack) > 1:
# 栈中剩余的都是右边没有更低的
ans = max(ans, heights[stack.pop()] * (n - 1 - stack[-1]))
return ans
자바:
class Solution {
public int largestRectangleArea(int[] heights) {
int ans = 0;
final int n = heights.length;
Deque<Integer> stack = new LinkedList<>();
stack.push(-1);
for (int i = 0; i < n; ++i) {
while (stack.size() > 1 && heights[stack.peek()] > heights[i]) {
// 栈中比当前位置高的那些待确定右边界的下标都可以确定右边界了
ans = Math.max(ans, heights[stack.pop()] * (i - 1 - stack.peek()));
}
// 入栈,等到能够确定右边界时处理
stack.push(i);
}
while (stack.size() > 1) {
// 栈中剩余的都是右边没有更低的
ans = Math.max(ans, heights[stack.pop()] * (n - 1 - stack.peek()));
}
return ans;
}
}
이 글을 읽어주셔서 정말 감사합니다~
[좋아요] [수집] [댓글] 3회 연속 환영합니다~
입니다 포기하는 것은 어렵지 않습니다. 그러나 인내심은 멋져야 합니다~
우리 모두 매일 조금씩 발전할 수 있기를 바랍니다~
이 기사는 원본 블로그~두 번째 보스의 흰모자: https://le-yi.blog.csdn.net/