leetcode 브러시 질문 일기-[84. 막대 차트에서 가장 큰 사각형]

함께 만들고 함께 성장하기 위해 함께 노력하십시오! "너겟 데일리 뉴플랜·8월 업데이트 챌린지" 참여 32일차 입니다 . 이벤트 상세보기 클릭

주제 설명

히스토그램에서 각 열의 높이를 나타내는 n개의 음이 아닌 정수가 주어집니다. 각 열은 서로 인접하고 너비가 1입니다.

이 히스토그램에서 그릴 수 있는 직사각형의 최대 면적을 찾으십시오.

 

예 1:

이미지.png

입력: heights = [2,1,5,6,2,3] 출력: 10 설명: 가장 큰 사각형은 그림의 빨간색 영역이며 영역은 10입니다. 예 2:

이미지.png

입력: 높이 = [2,4] 출력: 4  

힌트:

  • 1 <= heights.length <=105
  • 0 <= 높이[i] <= 104

문제 해결 아이디어

배열 높이가 주어지면 히스토그램을 시뮬레이션하고 배열의 각 요소는 각 좌표의 열 높이에 해당하고 각 열의 너비는 1입니다.

이 질문은 받을 수 있는 최대 강우량에 대한 질문과 약간 비슷합니다. 그러나 여기서 차이점은 형성할 수 있는 직사각형이며, 그 질문은 최대 중첩 면적, 즉 여러 직사각형이 중첩될 수도 있다는 것입니다.

먼저 히스토그램에서 각 열이 형성할 수 있는 가장 큰 직사각형을 구하는 방법을 결정합니다.

높이가 [2,3,4,1,2]라고 가정합니다.

그러면 첫 번째 열에 의해 형성될 수 있는 최대 사각형은 해당 위치에서 역방향으로 검색된 것보다 첫 번째 작은 값의 위치에 따라 달라집니다. 현재 요소의 높이는 자체입니다(이보다 높은 것은 직사각형일 수 없음).

즉, 제1 기둥(2)에 의해 형성될 수 있는 가장 큰 직사각형은 2*3=6이고;

계속해서 두 번째 열 3을 찾으면 뒤로 보이고 첫 번째 열이 3에 있는 것보다 작지만 여기에는 여전히 이전 요소가 있으므로 첫 번째 열을 제외하고 나머지 열은 첫 번째 열 A를 기대해야 합니다. 그것보다 작은 기둥. 따라서 두 번째 열의 최대 직사각형 영역은 3*(1+1)=6입니다.

이런 식으로 마지막 열을 찾을 때까지 이 때 마지막 열에는 후속 열이 없기 때문에 자신보다 작은 첫 번째 열만 기대하면 됩니다. 열이 없으면 자기 자신, 즉, 마지막 열은 2의 최대 직사각형 영역을 형성할 수 있습니다.

배열 높이에서 최대 직사각형 영역을 찾기 위해 현재 요소는 앞쪽 또는 오른쪽보다 작은 첫 번째 요소를 찾은 다음 합산하는 것임을 알 수 있습니다. 그래서 여기에서 우리는 센티넬 노드의 아이디어를 적용할 수 있습니다. 즉, 모든 노드가 동일한 작업을 사용하고 코드 복잡성을 줄일 수 있도록 존재하지 않는 노드를 생성합니다.

이와 같이 방향에 따라 첫 번째 크거나 작은 값을 찾아야 하며, 모노토닉 스택 을 사용하여 해결할 수 있습니다.

암호

public static int largestRectangleArea(int[] heights) {
    int length = heights.length;
    int[] left = new int[heights.length];
    int[] right = new int[heights.length];
    // 向前寻找第一个小于它的柱子
    ArrayDeque<Integer> arrayDeque = new ArrayDeque<>();
    for (int i=0; i< length; i++) {
        // 单调栈中只要有值就可以一直弹出
        while (!arrayDeque.isEmpty() && heights[arrayDeque.peek()] >= heights[i]) {
            arrayDeque.poll();
        }
        // 此时单调栈中的元素一定是第一个小于当前元素的值,如果为空,则直接将这个位置赋值为-1
        left[i] = arrayDeque.isEmpty() ? -1 : arrayDeque.peek();
        arrayDeque.push(i);
    }
    // 清空单调栈
    arrayDeque.clear();
    for (int i=length-1; i>= 0; i--) {
        // 单调栈中只要有值就可以一直弹出
        while (!arrayDeque.isEmpty() && heights[arrayDeque.peek()] >= heights[i]) {
            arrayDeque.poll();
        }
        // 此时单调栈中的元素一定是第一个小于当前元素的值,如果为空,则直接将这个位置赋值为n
        right[i] = arrayDeque.isEmpty() ? length : arrayDeque.peek();
        arrayDeque.push(i);
    }
    // 获取最大面积
    int max = 0;
    for (int i=0 ; i < length ; i ++) {
        max = Math.max(max,heights[i] * (right[i]-left[i]-1));
    }
    return max;
}
复制代码

추천

출처juejin.im/post/7136828780630245390