2805번 나무자르기
binary search
실버 II
💡문제 분석 요약
binary search 이진탐색
💡알고리즘 설계
절단기 범위를 start,end로 설정한다.
이진 탐색으로 해당 길이의 절단기로 잘랐을 때 모을 수 있는 나무를 cut에 넣고, 만약 cut이 크면 범위를 줄여줘야 하므로 end = mid -1로 설정한다.
여기서 절단기의 최댓값을 알아야 하므로 return end값을 해야한다. 이때 값이 end에 담겨서 최종 반환되므로, cut==m인 경우 while문은 start가 end보다 커야 끝나므로 start의 범위를 위로 올려서 다시 while에 돌려야 한다. 즉 start를 최대한 높여야 끝난다.
반대로 start를 반환하는 최솟값을 구하는 경우, start가 end 보다 커야 끝나므로 cut≤m일때 end의 값을 최대한으로 내려야 끝난다. 즉 start를 리턴해야되므로 start는 건드리지 않고 end를 조정해서 끝내야한다.
💡코드
import sys
input = sys.stdin.readline
n,m = map(int,input().strip().split())
trees = list(map(int,input().strip().split()))
#binary search
start,end = 1,max(trees)
while start<=end :
cut= 0
mid = (start+end)//2
for tree in trees:
if tree>mid:
cut += tree-mid
if cut<m: #더 잘라야 하므로 절단기를 낮춰야 함.
end = mid -1
else:
start= mid +1
print(end)
💡틀린 이유
일단, start의 값을 1로 잡지 않고 tree의 최솟값으로 잡은 것이 화근이었다. 애초부터 출력값은 0도 될 수 있고 최댓값만 확정 된 것인데 (나무 보다 더 긴 절단기로 자를 수 없기에) 최솟값을 마음대로 정해버렸다.
💡시간복잡도
n log n
💡 기억할정보
- 범위 중 최댓값을 반환해야하는 경우, mid==비교값이 되는 경우에 최솟값을 변경하고, 최솟값을 변환하는 경우에는 최댓값을 변경해줘야 한다. 왜냐하면 while문의 탈출 조건이 start>end이기 때문이다.