[복기] 6549번: 히스토그램에서 가장 큰 직사각형

2023. 5. 15. 20:46·IT/BOJ 문제정리

문제

백준 1725번: 히스토그램
백준 6549번: 히스토그램에서 가장 큰 직사각형

1725번과 6549번은 사실 같은 문제이다. 분할정복 문제라서 도전해봤는데 생각보다 어렵다. 알고보니 스택으로 푸는 법과 분할정복으로 푸는 법, 세그먼트트리로 푸는 법이 따로 있다고 한다. 스택으로 푸는 것이 시간복잡도가 O(n)으로 가장 빠르고 쉬운 풀이라고 하는데, 그래도 어렵다. 나는 솔루션을 보고 이해했다. 스택으로 될 것 같아서 도전했는데 안되더라. 분할정복 솔루션도 봤는데 그건 더 어렵다..

나의 풀이

스택으로 풀 수 있을 것 같아서 도전했다. 나중에 보니 스택으로 푸는 법과 로직은 거의 같았는데 가장 긴 아래 밑변 구하는 것을 못해서 틀렸다. 아쉽군. 우선 나는 두 가지 방식을 사용했다. 첫 번째는 아래 솔루션 1과 거의 유사하다. 두 번째는 스택과 재귀를 사용했다. 히스토그램의 높이가 증가할 때 스택에 담고, 감소하면 재귀를 사용해 스택에 담겨있는 직사각형의 최대 넓이를 구하는 방식을 사용했다. 그러나 틀렸다. 솔루션을 보고나니 왜 틀렸는지 알았다.

솔루션 1: 스택

히스토그램 스택 풀이

솔루션은 간단하기 그지없다. 왼쪽에서부터 시작하여 히스토그램이 증가하면 stack에 담고, stack[-1] 보다 작은 값을 만나면 그보다 작거나 같은 값이 보이기 전까지 stack.pop()을 한다. pop을 하면서 직사각형의 넓이를 구하고 최대값을 갱신하면 된다.

import sys
input = sys.stdin.readline

n = int(input())
a = [int(input()) for _ in range(n)]

answer = a[0]
stack = [0]
for i in range(1, n):
    while stack and a[stack[-1]] > a[i]:
        mIdx = stack.pop()
        if stack:
            width = i - stack[-1] - 1
        else:
            width = i
        answer = max(answer, width*a[mIdx])
    stack.append(i)

while stack:
    mIdx = stack.pop()
    if stack:
        width = n - stack[-1] - 1
    else:
        width = n
    answer = max(answer, width*a[mIdx])

print(answer)

솔루션 2: 분할정복

히스토그램 분할정복 풀이

분할정복 알고리즘을 이용해서 해결할 수 있다. 분할 정복은 주어진 문제를 부분 문제들로 나누어 푸는 것이기 때문에 이 문제 또한 히스토그램을 나누어 푸는 것이 핵심이다. 따라서 주어진 n개의 막대그래프를 절반으로 나누게 되면 결국 찾고자 하는 가장 큰 직사각형은 다음 세가지중 하나에 속하게 된다.

1. 왼쪽 부분 문제에서 가장 큰 직사각형이 존재하는 경우
2. 오른쪽 부분 문제에서 가장 큰 직사각형이 존재하는 경우
3. 가장 큰 직사각형이 왼쪽 부분 문제와 오른쪽 부분 문제에 걸쳐 있는 경우

1번과 2번의 경우에는 재귀 호출을 이용하면 되고, 3번의 경우만 특별히 고려한다면 답을 구할 수 있을 것이다.

솔루션 3: 세그먼트 트리

'IT > BOJ 문제정리' 카테고리의 다른 글

[복기] 2252번: 줄 세우기  (0) 2023.05.17
[복기] 1655번: 가운데를 말해요  (0) 2023.05.15
[복기] 8983번: 사냥꾼  (0) 2023.05.15
[복기] 2470번: 두 용액  (0) 2023.05.15
[복기] 2110번: 공유기 설치  (0) 2023.05.15
'IT/BOJ 문제정리' 카테고리의 다른 글
  • [복기] 2252번: 줄 세우기
  • [복기] 1655번: 가운데를 말해요
  • [복기] 8983번: 사냥꾼
  • [복기] 2470번: 두 용액
KimCookieYa
KimCookieYa
무엇이 나를 살아있게 만드는가
  • KimCookieYa
    쿠키의 주저리
    KimCookieYa
  • 전체
    오늘
    어제
    • 분류 전체보기 (577)
      • 혼잣말 (88)
      • TIL (3)
      • 커리어 (24)
        • Sendy (21)
        • 외부활동 기록 (2)
      • 프로젝트 (186)
        • 티스토리 API (5)
        • 코드프레소 체험단 (89)
        • Web3 (3)
        • Pint OS (16)
        • 나만무 (14)
        • 대회 (6)
        • 정글 FE 스터디 (16)
        • MailBadara (12)
        • github.io (1)
        • 인공지능 동아리, AID (5)
        • 졸업과제 (18)
        • OSSCA 2024 (1)
      • 크래프톤 정글 2기 (80)
      • IT (170)
        • 코딩 (4)
        • CS (18)
        • 에러 (5)
        • 블록체인 (23)
        • Front-End (41)
        • 알고리즘&자료구조 정리 (3)
        • 코딩테스트 (3)
        • BOJ 문제정리 (41)
        • WILT (12)
        • ML-Agents (4)
        • 강화학습 (1)
        • Android (0)
        • LLM (2)
      • 전공 (1)
        • 머신러닝 (1)
      • 자기계발 (20)
        • 빡공단X베어유 (2)
        • 독서 (15)
  • 블로그 메뉴

    • 홈
    • 방명록
    • Github
    • Velog
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    블록체인
    해커톤
    numpy
    Flutter
    코드프레소
    JavaScript
    딥러닝
    글리치해커톤
    니어프로토콜
    MailBadara
    RNN
    사이드프로젝트
    부산대
    Pint OS
    졸업과제
    알고리즘
    자바스크립트
    리액트
    pintos
    docker
    react
    핀토스
    나만무
    OS
    파이썬
    NEAR Protocol
    센디
    크래프톤정글
    프로그래머스
    머신러닝
  • hELLO· Designed By정상우.v4.10.3
KimCookieYa
[복기] 6549번: 히스토그램에서 가장 큰 직사각형
상단으로

티스토리툴바