LeetCode 84

Largest Rectangle in Histogram

Posted by Damin on July 14, 2023

Largest Rectangle in Histogram

  • 문제
    • 주어진 그래프에서 가장 넓은 직사각형의 넓이를 구하라
  • 생각해볼 수 있는 것
    • 가장 높은 막대를 기준으로 넓이를 측정
      • 낮은 막대가 많고 길이가 긴 경우에는 성립하지 않는다
    • 가장 낮은 것을 기준으로 넓이 측정 (0 제외)
      • 높은 막대가 많고 길이가 짧은 경우에는 성립하지 않는다

    중간 길이의 막대가 기준이 되어 가장 넓은 직사각형이 될 수 있고, 가장 낮은 막대가 기준이 되어 가장 넓은 직사각형이 될 수 있고, 가장 높은 막대가 기준이 되어 가장 넓은 직사각형이 될 수 있다

    모든 경우를 조사해야 가장 넓은 직사각형을 알 수 있다 n은 10만이기 때문에 n^log(n) 안에 풀어야 한다

  • 풀이
    • 막대의 길이와 인덱스를 스택에 삽입
    • 핵심 : 스택은 항상 오름차순으로 유지 (맨 위에 있는 막대의 높이보다, 낮은 막대를 발견한다면 스택 재정렬)
      • 낮은 막대가 들어왔다면 더 이상 넓이를 늘릴 수 없다
      • 스택에 지금 들어온 막대보다 큰 막대들은 전부 POP 해주면서 넓이를 측정한다
        • 지금까지 오름차순이었기에 먼저 들어온 막대들은 현재 인덱스까지 직사각형을 만들 수 있다
      • 더 이상 낮은 막대가 없다면 가장 최근에 삭제된 인덱스를 현재 들어오는 막대의 인덱스에 대입
        • 더 이상 낮은 막대가 없다는 뜻은 삭제된 인덱스까지는 직사각형을 만들 수 있다는 뜻
    • 모든 막대를 검사하고, 스택에 남아있는 막대가 있다면 그래프의 길이만큼 넓이 측정
    • 가장 큰 값 리턴

Code

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
import java.util.*;

class Pair {
    int index;
    int num;

    public Pair(int index, int num) {
        this.index = index;
        this.num = num;
    }
}

class Solution {
    public int largestRectangleArea(int[] heights) {
        Stack<Pair> stack = new Stack<>();
        int answer = 0;

        for(int i=0;i<heights.length;i++) {
            int now = heights[i];

            if(stack.size() == 0)
                stack.push(new Pair(i, now));

            else {
                Pair top = stack.peek();

                if(top.num < now)
                    stack.push(new Pair(i, now));

                else {
                    int lastIndex = 0;
                    while(!stack.isEmpty()) {
                        lastIndex = top.index;
                        top = stack.pop();
                        if(top.num < now) {
                            stack.push(top);
                            break;
                        }
                        answer = Math.max((i - top.index) * top.num, answer);
                    }

                    if(stack.isEmpty())
                        stack.push(new Pair(top.index, now));
                    else
                        stack.push(new Pair(lastIndex, now));
                }
            }
        }

        while(!stack.isEmpty()) {
            Pair top = stack.pop();
            answer = Math.max((heights.length - top.index) * top.num, answer);
        }

        return answer;
    }
}