야근 피로도는 야근을 시작한 시점에서 남은 일의 작업량을 제곱하여 더한 값
N시간 동안 야근 피로도를 최소화하도록 하고자 할 때
1시간 동안 작업량 1만큼을 처리할 수 있다고 할 때,
퇴근까지 남은N시간과 각 일에 대한 작업량works에 대해
야근 피로도를 최소화한 값을 리턴하는 함수solution을 완성해주세요.
public class OvertimeScoreCalculator
{
public long Solution(int n, int[] works) {
long answer = 0;
List<int> worksList = works.ToList();
worksList.Sort();
worksList.Reverse();
int currentIndex = 0;
int maxIndex = 0;
int time = n;
while (time > 0)
{
//현재 확인한 값이 최대값과 같을 경우 현재 확인한 값이 최대 값이므로 해당 값을 1 감소
if (worksList[currentIndex] >= worksList[maxIndex])
{
worksList[currentIndex] = worksList[currentIndex] > 0 ? worksList[currentIndex]-1 : 0;
time--;
}
if (worksList[currentIndex] > worksList[maxIndex])
{
maxIndex = currentIndex;
}
if (worksList[currentIndex] <= worksList[maxIndex])
{
currentIndex = currentIndex + 1 < worksList.Count ? currentIndex + 1 : 0;
}
}
foreach (int i in worksList)
{
answer += (long)Math.Pow(i, 2);
}
return answer;
}
}
works의 값을 각각 제곱해서 더한 것이 최소가 되게 해야하므로works배열 내에 값들의 편차를 줄이는 것이 중요하다고 판단
1. 배열을 리스트로 변환 (Sort()기능을 사용하기 위해)
2. 해당 리스트를 반전 (가장 큰 값이 제일 앞에 오도록 하기 위해)
3.n만큼 반복하며 리스트의 가장 앞에 있는 값을 1 감소
4. 감소 후 다시 리스트 정렬 + 반전이러한 방식을 사용해 답은 찾을 수 있었으나 효율성 문제를 맞닥뜨림
- 반복문 내에서 정렬 및 반전을 실시하므로 시간복잡도가 높아짐
while (time > 0)
{
//현재 확인한 값이 최대값과 같을 경우 현재 확인한 값이 최대 값이므로 해당 값을 1 감소
if (worksList[currentIndex] >= worksList[maxIndex])
{
worksList[currentIndex] = worksList[currentIndex] > 0 ? worksList[currentIndex]-1 : 0;
time--;
}
if (worksList[currentIndex] > worksList[maxIndex])
{
maxIndex = currentIndex;
}
if (worksList[currentIndex] <= worksList[maxIndex])
{
currentIndex = currentIndex + 1 < worksList.Count ? currentIndex + 1 : 0;
}
}
n회 동안 최댓값을 찾아 1씩 줄이는 동작을 실시하는 것이 중요currentIndex의 값이 최댓값의 인덱스maxIndex의 값보다 크거나 같다면 해당 위치가 최댓값이므로 1 감소하고 time을 1 감소maxIndex를 갱신