[BOJ][P5] 6549 히스토그램에서 가장 큰 직사각형

2025. 10. 1. 09:36·알고리즘 문제풀이
반응형

문제 내용

입력은 테스트 케이스 여러 개로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 직사각형의 수 n이 가장 처음으로 주어진다. (1 ≤ n ≤ 100,000) 그 다음 n개의 정수 h1, ..., hn (0 ≤ hi ≤ 1,000,000,000)가 주어진다. 이 숫자들은 히스토그램에 있는 직사각형의 높이이며, 왼쪽부터 오른쪽까지 순서대로 주어진다. 모든 직사각형의 너비는 1이고, 입력의 마지막 줄에는 0 6이 하나가 주어진다

히스토그램 내에서 만들 수 있는 가장 큰 직사각형의 넓이를 구하는 문제다.

문제 접근 (의식의 흐름대로)

딱 문제를 보고 들었던 생각들을 정리하면 다음과 같다.

  • 일단 n이 10만이고, 직사각형 높이가 10억이니까 이걸 전부 반복시키면 안되겠다
    시간 복잡도를 무조건 생각해야겠다.
  • 높이가 10억이나 되니, 넓이를 계산하다 보면 int 범위를 넘을 수 있겠고. 결과값 담을 자료형은 long으로 쓰는 건 일단 확정
  • 근데 변형되는 넓이를 어떻게 구해야 할지, 최대 넓이가 되는 형태를 어떻게 찾아야 할지 전혀 감이 안 왔다. DP를 써야 하나?
  • 결국 풀지 못하고 힌트를 봤고. '세그먼트 트리'라는 키워드가 있어서 이 부분을 공부하고 다시 풀어보기를 했으나 결국 못풀었다.

회고 & 풀이 방법

→ 스택 자료구조를 위한 풀이방법

→ 분할 정복 풀이 방법

→ 세그먼트 트리를 이용한 풀이방법

총 3가지가 있다는것을 알았다.

import java.io.*;
import java.util.*;

public class Main {

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuilder sb = new StringBuilder();

    public static void main(String[] args) throws IOException {

        while (true) {
                st = new StringTokenizer(br.readLine());

                int n = Integer.parseInt(st.nextToken());

                if (n == 0) break;

                int[] h = new int[n + 1];

                for (int i = 0; i < n; i++) {
                    h[i] = Integer.parseInt(st.nextToken());  // 각 막대의 높이가 들어감
                }

                Deque<Integer> stack = new ArrayDeque<>(n + 1);

                long max = 0;  // 최대값

                for (int i = 0; i <= n; i++) {
                    int cur = h[i]; // cur 은  0 ~ n 까지에서 해당 번호의 막대 높이

                    while (!stack.isEmpty() && h[stack.peek()] > cur) { // 스택이 비어있때는 -> h[stack.peek()] > cur 를 실행하지 않음
                        int top = stack.pop();

                        int left = stack.isEmpty() ? 0 : stack.peek() + 1;
                        long area = (long) h[top] * (i - left);

                        if (area > max) max = area;
                    }

                    stack.push(i);
                }

                sb.append(max).append('\n');
            }

            System.out.print(sb);
    }

}

일단 내가 푼 풀이는 아니지만 굉장히 깔끔한게 stack 으로 푼 방법이다.

핵심 코드인 아래만 봐도 무방하다

  for (int i = 0; i <= n; i++) {
        int cur = h[i]; // cur 은  0 ~ n 까지에서 해당 번호의 막대 높이

        while (!stack.isEmpty() && h[stack.peek()] > cur) { // 스택이 비어있때는 -> h[stack.peek()] > cur 를 실행하지 않음
            int top = stack.pop();

            int left = stack.isEmpty() ? 0 : stack.peek() + 1;
            long area = (long) h[top] * (i - left);

            if (area > max) max = area;
        }

        stack.push(i);
    }

h[i] 와 i 를 이해하고 while (!stack.isEmpty() && h[stack.peek()] > cur) {} 이 부분만 이해하면 될거 같다.

해당 문제는 BOJ 17298 문제랑도 비슷한데 해당 코드를 해석하면

!stack.isEmpty() 은 stack의 비어있는지 없는지를 확인하고 이를 확인하면

h[stack.peek()] > cur 를 통해 현재 stack 의 index 값을 peek()을 통해 확인 하여 스택 값을 호출하는 형식이다 . 처음에 이해가 안됬던 부분은? !stack.isEmpty() && h[stack.peek() 이 부분에서 stack에 값이 없는데 peek 이 어떻게 가능한지라는 의문이 있었다. → 해당부분은 && 의 연산으로 앞부분의 참/거짓 여부를 먼저 파악하기 때문에 앞에 false 인 순간 뒤에 stack의 peek은 동작하지 않는다고 한다.

이번 문제와 오큰수를 풀어본 후기로는 while (!stack.isEmpty() && h[stack.peek()] > cur) {} 이 부분을 통해 stack의 흐름제어를 이용하는것도 하나의 알고리즘 방법이라는것을 알았다.

구현도 쉽지만 아이디어적으로 생각이 나기 힘든 부분이었다고 생각한다.

일주일뒤에 다시 풀어봐야겠다.

반응형

'알고리즘 문제풀이' 카테고리의 다른 글

[BOJ][G5] 2504 괄호의값  (0) 2025.09.27
[BOJ][S3] 17413_단어뒤집기2  (0) 2025.09.26
[SWEA][D2] 1940. 가랏! RC카 Java  (1) 2025.06.04
[SWEA][D2] 1945. 간단한 소인수분해 Java  (0) 2025.06.04
[SWEA][D2] 1288. 새로운 불면증 치료 Java  (0) 2025.06.04
'알고리즘 문제풀이' 카테고리의 다른 글
  • [BOJ][G5] 2504 괄호의값
  • [BOJ][S3] 17413_단어뒤집기2
  • [SWEA][D2] 1940. 가랏! RC카 Java
  • [SWEA][D2] 1945. 간단한 소인수분해 Java
WHITE_FROST
WHITE_FROST
개발공부리뷰블로그
    반응형
  • WHITE_FROST
    하얀하얀IT
    WHITE_FROST
  • 전체
    오늘
    어제
    • 분류 전체보기 (119)
      • Stack (43)
        • Next.js (7)
        • React (12)
        • React-Native (15)
        • TypeScript (0)
        • Python (2)
        • JavaScript (2)
        • Android (1)
        • DB (2)
        • JAVA (1)
      • Obsidian (1)
      • AI (3)
      • AI Tools (0)
      • Tools (0)
      • Mac (0)
      • Error (7)
      • 알고리즘 정리 (6)
      • 알고리즘 문제풀이 (46)
      • 공부일상 (4)
      • 개발 도구 & 라이브러리 (0)
      • 정보처리기사 (0)
      • 기타 (6)
      • Tip (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Next.js
    mongodb cloud
    Python
    코딩테스트
    리액트네이티브
    오블완
    코테준비
    boj
    hooks
    React-Native cli
    알고리즘
    SWEA
    ReactHook
    react-native
    javascript
    프로그래머스
    D2
    React Hooks
    java
    티스토리챌린지
    d1
    코테
    react
    Expo
    ios
    error
    react-native-maps
    reactnative
    mongoDB Atlas
    백준
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
WHITE_FROST
[BOJ][P5] 6549 히스토그램에서 가장 큰 직사각형
상단으로

티스토리툴바