야근 피로도는 야근을 시작한 시점에서 남은 일의 작업량을 제곱하여 더한 값이다. 1시간 동안 작업량 1만큼을 처리할 수 있다고 할 때, 퇴근까지 남은 N 시간과 각 일에 대한 작업량 works에 대해 야근 피로도를 최소화한 값을 구하면 되는 문제
from typing import List
def solution1(n: int, works: List[int]) -> int:
'''
효율성 시간 초과 코드
매번 정렬해서 최대값을 줄여주는 방식
'''
if sum(works) <= n: # 예외 처리 : 남은 작업량의 합이 n을 넘지 않으면 피로도는 0임
return 0
works.sort(reverse=True) # 내림차순 정렬
while n > 0: # n이 남아있는동안
works[0] -= 1 # 최대값 -1
works.sort(reverse=True) # 최대값 인덱스 업데이트
n-=1
return sum(map(lambda x:x**2, works))
from typing import List
def get_need_decrease(works: List[int], max_value: int) -> int:
'''
최대값을 max_value로 설정했을 때 works에서 빼어야 할 크기를 반환한다.
'''
need_decrease: int = 0
for work in works:
if work > max_value:
need_decrease += (work - max_value)
return need_decrease
def solution(n: int, works: List[int]) -> int:
if sum(works) <= n:
return 0
works.sort()
start, end = 0, max(works)
while start <= end: # 최대 값을 num으로 설정할 때 빼어야 하는 수가 n을 넘지 않는
mid = (start+end)//2 # 최대 num을 찾기
if get_need_decrease(works, mid) <= n:
end = mid-1
else:
start = mid+1 # 이 경우 최종 최대 num은 start에 담김
for i in range(len(works)-1, -1, -1): # 최대값을 start로 두고 실제 works에서 빼주기
if works[i] > start:
n -= (works[i]-start)
works[i] = start
else:
break
i = len(works)-1 # 최대값을 num으로 맞춰주었을 때 n이 남은 경우
while n > 0 and i >=0: # 가장 큰 수부터 골고루 빼줘야 함(현재 오름차순 정렬되어 있음)
works[i]-=1
n-=1
if not works[i] or works[i]<works[i-1]: # 음수가 될 순 없음, 전체 1씩 낮출 수 없음이 보장되어있기 떄문에
i-=1 # 큰 수부터 골고루 낮춰야 한다.
return sum(map(lambda x:x**2, works))
🙏 문제 접근 방법 및 코드에 대한 피드백과 질문은 환영입니다!
본 문제의 다른 풀이 및 피드백, 전체 문제 풀이 순서는 위 알고리즘 스터디 Repository에서도 확인 가능합니다.