[Programmers] 야근 지수

1 분 소요

문제

출처: programmers.co.kr/learn/courses/30/lessons/12927


풀이

구현 1

야근 지수를 최소화하기 위해서는 각 작업량 간 차이가 가장 적어져야 한다.

  • 이를 위해 남은 시간 n만큼 works 배열을 순회하며 그 때 그 때 작업량의 최댓값을 1씩 낮춰줘야 한다.
  • 이 과정에서 정렬, 인덱싱 등을 사용하면 효율성 테스트를 통과하기가 매우 어렵다.

우선순위 큐 자료구조를 사용하기 위해 파이썬 내장 모듈인 heapq 모듈에서 힙 자료구조를 사용하여 구현했다.

  • 다만, 최대 힙을 구현해야 하기 때문에 주어진 works 배열의 작업량을 음수로 만든다.
  • 작업량을 줄일 때는 1씩 빼는 것이 아니라 1씩 더한다.

answer를 구할 때는 남은 작업량을 제곱해서 구하기 때문에, 음수를 제곱해서 더하나 양수를 제곱해서 더하나 상관이 없다.

import heapq

def solution(n, works):
    if n >= sum(works): # 야근을 하지 않아도 되는 경우
        return 0
    
    # 작업량을 최대힙으로 구현
    works_heap = [] 
    for work in works:
        heapq.heappush(works_heap, -work)
    
    # 작업량 최댓값 낮춰 주기
    while n:
        max_work = heapq.heappop(works_heap)
        max_work += 1
        n -= 1
        heapq.heappush(works_heap, max_work)
        
    # 최종 야근지수
    answer = 0
    for work in works_heap:
        answer += (work**2)
        
    return answer

구현 2

통과가 되긴 하나, 예외 처리를 해야 하고 가독성도 좋지 않다.

def solution(n, works):
    answer = 0
    if n >= sum(works):
        return answer
    else:
        works.sort(reverse = True) # 한 번만 정렬하자 처음에.
        i = 0 # 인덱스
        try:
            while n > 0:
                if works[i] == works[i+1]:
                    i += 1
                elif (works[i] - works[i+1]) * (i+1) <= n:
                    n -= (works[i] - works[i+1]) * (i+1)
                    for j in range(i+1):
                        works[j] -= (works[i] - works[i+1])
                    i += 1
                else:
                    for j in range(i+1):
                        works[j] -= 1
                        n -= 1
                        if n == 0:
                            break
        except IndexError:
            q, r = n // len(works), n % len(works)
            if q > 0 :
                for i in range(len(works)):
                    works[i] -= q
                n -= q * len(works)

            while n > 0:
                for i in range(len(works)):
                    works[i] -= 1
                    n -= 1
                    if n == 0:
                        break

        for work in works:
            answer += work * work

        return answer


다른 사람의 풀이

프로그래머스 사이트에 올라온 다른 풀이의 접근법들도 비슷하게 최대 작업량을 1씩 감소시켜 주었다. 다만, 문제가 개편되어 효율성 테스트를 통과하지 못하는 경우가 있다고 한다.



hit count image

댓글남기기