코딩테스트/프로그래머스 level 3

[프로그래머스 level_3] 야근 지수 for JAVA

냠냠:) 2020. 5. 5. 02:14

https://programmers.co.kr/learn/courses/30/lessons/12927

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

[문제 설명]

 

회사원 Demi는 가끔은 야근을 하는데요, 야근을 하면 야근 피로도가 쌓입니다. 야근 피로도는 야근을 시작한 시점에서 남은 일의 작업량을 제곱하여 더한 값입니다. Demi는 N시간 동안 야근 피로도를 최소화하도록 일할 겁니다.Demi가 1시간 동안 작업량 1만큼을 처리할 수 있다고 할 때, 퇴근까지 남은 N 시간과 각 일에 대한 작업량 works에 대해 야근 피로도를 최소화한 값을 리턴하는 함수 solution을 완성해주세요.제한 사항

  • works는 길이 1 이상, 20,000 이하인 배열입니다.
  • works의 원소는 50000 이하인 자연수입니다.
  • n은 1,000,000 이하인 자연수입니다.

입출력 예

works n result
[4, 3, 3] 4 12
[2, 1, 2] 1 6
[1,1] 3 0

입출력 예 설명

 

입출력 예 #1
n=4 일 때, 남은 일의 작업량이 [4, 3, 3] 이라면 야근 지수를 최소화하기 위해 4시간동안 일을 한 결과는 [2, 2, 2]입니다. 이 때 야근 지수는 22 + 22 + 22 = 12 입니다.

 

입출력 예 #2
n=1일 때, 남은 일의 작업량이 [2,1,2]라면 야근 지수를 최소화하기 위해 1시간동안 일을 한 결과는 [1,1,2]입니다. 야근지수는 12 + 12 + 22 = 6입니다.

 

[풀이]

나는 배열을 일단 내림차순으로 정렬을 하여 인덱스를 가지고 n번만큼 반복하며 아래의 조건을 부합하게끔 작업을 했다.

  • idx = 0 즉, 첫 번째 요소는 가장 큰 요소이므로 idx가 0일 땐 값을 1만 빼주기만 한다.
  • 첫 번째 요소를 계속 빼다 두 번째로 큰 요소보다 작아질 때 idx를 +1 해주어 다음 인덱스로 넘어간다.
  • 지금 idx가 가리키고 있는 값보다 다음 값이 작다면 idx가 가리키는 값을 -1을 해주고 idx를 0으로 만들어 처음으로 돌아간다.

ex) n = 100, work =[2,15,22,55,55]

idx 0, 1은 22보다 계속 크므로 둘이 반복되어 -1이 됨
n=68번 부터 22보다 작아지므로 이제는 22도 포함시켜서 -1해줌
90부터 15보다 작아지므로 15까지 포함시켜 -1해줌

[코드]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.util.Arrays;
import java.util.Collections;
 
public class NightOvertime {
    public long solution(int n, int[] work) {
        long answer = 0;
        Integer[] works = Arrays.stream(work).boxed().toArray(Integer[]::new);
        Arrays.sort(works , Collections.reverseOrder());
        work = Arrays.stream(works).mapToInt(Integer::intValue).toArray();
        
        int idx = 0;                                    //현재 값을 가르키는 인덱스
        boolean flag = true;                            //배열 첫 원소를 다루고 있는지 true = (idx =0)
        for(int i = 0;  i < n; i++) {
            if(idx == work.length-1) {                    //마지막 까지 갔을 때는 idx를 0으로 초기화해줌
                work[idx]--;
                idx = 0;
                flag = true;
                continue;
            }
            
            if(work[idx] > work[idx+1]) {                //지금 idx값이 next idx값 보다 크면
                if(flag) {                                //idx가 0이면
                    work[idx]--;                        //빼주기만 한다.
                }else {
                    work[idx]--;                        //idx가 0이아니면 0을 만들고 flag를 true로 만들어준다.
                    idx = 0;
                    flag = true;
                }
            }else if(work[idx] < work[idx+1]) {            //next idx 값이 크면
                flag = false;                            //첫요소를 다루는 것이 아니므로 false
                idx++;                                    //현재 값이 작다면 다음 값을 다뤄야하므로
                work[idx]--;
            }else if(work[idx] == 0) {                    //인덱스가 마지막도 아닌데 0을 만나면 모든 배열이 0이므로
                idx = 0;
                work[idx]--;
            }else {                                        //idx next idx 값이 같을 때
                flag = false;                            
                work[idx]--;
                idx++;
            }
        }
        
        if(work[0< 0return 0;
        
        for(long a : work) answer += (long) Math.pow(a, 2);
        
        
        return answer;
    }
}
cs

프로그래머스 테스트 케이스 통과

느낀 점 : 처음에는 문제가 무슨 말을 하는지 잘 몰라서 3분 정도 문제를 이해하는 시간을 갖었다.. 문제를 이해하고 쉽겠거니 생각해서 문제를 풀려고 하는데 의외로 조건이 조금 있어서 풀 방향을 설계하고 적어 보았다. 요즘 들어 계속 느끼는 것이지만 내가 생각하는 것들을 도식화하고 풀어가는 과정을 조금 귀찮더라도 적으면서 하면 원래 푸는 시간보다 훨씬 줄어드는 것 같다.

반응형