////
Search

히스토그램에서 가장 큰 직사각형

소스코드

import sys input = sys.stdin.readline result = [] # 결과 출력용 리스트 inputs = [] # 입력 라인 저장용 while True: line = input().strip().split() if line == ['0']: break n = int(line[0]) arr = list(map(int, line[1:])) inputs.append((n, arr)) # 튜플 형태 : (직사각형 수, n개의 높이 배열) # 중간에 겹치는 영역에 대한 크기를 구하는 함수 def get_crossing_size(arr, left_idx, right_idx, mid_idx): max_size = arr[mid_idx] min_height = arr[mid_idx] l = mid_idx r = mid_idx while left_idx < l or right_idx > r: # 오른쪽 먼저 확장해보기(그냥) if r < right_idx and (l == left_idx or arr[r+1] >= arr[l-1]): r += 1 min_height = min(min_height, arr[r]) else: l -= 1 min_height = min(min_height, arr[l]) max_size = max(max_size, min_height * (r - l + 1)) return max_size # 메인 함수 def recursive_get_largest_size(arr, left_idx, right_idx): if left_idx > right_idx: return 0 # 하나만 남은 경우 if left_idx == right_idx: return arr[left_idx] # 마법의 요정 구간 mid_idx = (left_idx + right_idx) // 2 left_side_size = recursive_get_largest_size(arr, left_idx, mid_idx - 1) right_side_size = recursive_get_largest_size(arr, mid_idx + 1, right_idx) mid_crossing_size = get_crossing_size(arr, left_idx, right_idx, mid_idx) return max(left_side_size, right_side_size, mid_crossing_size) for i in range(len(inputs)): n, arr = inputs[i] case_result = recursive_get_largest_size(arr, 0, n-1) result.append(case_result) print('\n'.join(map(str, result)))
Python
복사

풀이

입력에 대해서는
테스트 케이스가 정확히 몇 개라고 안 나와있고, 끝날 때는 0만 있다고 했으니, while문을 돌면서 0이 등장하는 순간까지 반복하고 해당하면 break를 만나 즉시 종료합니다.
inputs 배열에는 슬라이싱을 이용해서 n과 arr로 분리해 튜플 형태로 저장해둡니다.
inputs의 개수만큼 반복을 수행합니다.
각 케이스들은 메인 함수를 시작합니다.
이분탐색(재귀)을 진행합니다.
기저 조건은 하나만 남아 left_idx == right_idx인 경우입니다. 해당 인덱스의 높이를 반환합니다.
왼쪽 부분에서의 가장 큰 넓이, 오른쪽 부분에서의 가장 큰 넓이, 중앙 부분을 포함하는 경우에서의 가장 큰 넓이를 각각 구합니다.
3가지 경우에서의 가장 큰 값을 구합니다.
중앙 부분을 포함하는 경우에서의 가장 큰 넓이는 다음과 같이 구합니다.
중앙 부분에서 양쪽으로 뻗어나가며 최대값을 구합니다.
중앙에서 시작하는 이유는, 중앙이 포함된 경우를 우선 고려해야하지 않나 싶어서 선택했습니다.
l, r 인덱스를 두고 left_idx, right_idx에 도달할 때까지 계속 반복하며 가장 큰 넓이를 구해나갑니다.
메인 함수를 돌고 반환되는 값을 result 배열에 저장합니다.
result 배열을 join해 결과를 출력합니다.

복기

다른 부분은 다 괜찮았는데, get_crossing_size 함수에서 while 문의 조건을 거는 것과 if 문에서 오른쪽을 먼저 탐색하는 경우에서의 여러 조건들을 어떻게 설정해야할지 계속 망설였습니다.
if 문의 3가지 조건식과 논리연산자를 어떻게 해야 만족할 수 있는지를 캐치하지 못한 것에 대한 이유를 충분히 생각해보고 보완해야겠습니다.