Shiny Sky Blue Star

프로그래머스 문제 풀이/프로그래머스 (JAVA)

JAVA 프로그래머스 Lv.3 인사고과

gamja00 2024. 12. 9. 21:29

 

https://school.programmers.co.kr/learn/courses/30/lessons/152995

 


문제

  1. 입력으로 scores ( 1 <= n <= 100000 )이 입력으로 들어옴.
  2. scores 배열 각 행의 두 항목은 각각 한 사원의 [근무 태도 점수, 동료 평가 점수] 을 나타낸다.
  3. scores[0] 행은 완호의 점수( 근무 태도 점수, 동료 평가 점수 )이다.
  4. 어떤 사원이 임의의 사원보다 두 점수 ( 근무 태도 점수, 동료 평가 점수 ) 모두가 낮은 경우가 있다면 그 사원은 인센티브를 받지 못하게 된다.
  5. 인센티브를 받을 수 있는 사원일 경우 두 점수의 합이 높은 순서대로 인센티브를 차등 지급한다.
  6. 인센티브 지급 시에 두 점수의 합이 동일한 사원은 동석차로, 동석차 수만큼 다음 석차를 건너 뛴다.
  7. 완호가 인센티브를 받을 수 없을 경우 -1을 출력한다.

 

초기 코드

import java.util.Arrays;

class Solution {
    public int solution(int[][] scores) {
        int answer = 0;
        
        int[] wanho = scores[0];
        int wanhoScore = wanho[0] + wanho[1];

        Arrays.sort(scores, (o1, o2) -> o2[0] - o1[0]);
        Arrays.sort(scores, (o1, o2) -> {
            if (o1[0] == o2[0]) {
                return o1[1] - o2[1];
            }
            return 0;
        });

        if (scores[0][0] + scores[0][1] > wanhoScore) {
            answer++;
        }

        for (int i = 0; i < scores.length - 1; i++) {
            if (scores[i][1] <= scores[i + 1][1]) {
                if (scores[i + 1][0] + scores[i + 1][1] > wanhoScore) {
                    answer++;
                }
            } else {
                if (scores[i + 1][0] == wanho[0] && scores[i + 1][1] == wanho[1]) {
                    answer = -1;
                    break;
                }
            }
        }
        if(answer!=-1){
            answer++;
        }
        
        return answer;
    }
}

 

일단 정렬을 한 후 사용해야 될 것 같아서 정렬하는 방식을 다양하게 해봤다.

 

1. [ 오름차순, 오름차순 ]

2. [ 오름차순, 내림차순 ]

3. [ 내림차순, 오름차순 ]

 

[ 내림차순, 내림차순 ] 을 하지 않은 이유는 1번으로 정렬했을 때 문제가 잘 풀리지 않아서 내림차순도 마찬가지일 거라고 생각하여 시도하지 않았다.

 

따라서 2번과 3번 중에 고르면 되는데 둘 중 어느 것을 골라도 아마 문제를 풀 수 있지 않을까 싶다.

 

이 코드는 좀 코드가 유연하지 않다? 딱딱하다? 정적이다? 뭐라고 부르는 이름이 있었는데 까먹었다.

 

코드를 설명하자면

일단 완호의 점수인 scores[0]행을 int 1차원 배열인 wanho에 저장하도록 하였다.

완호의 총 점수와 다른 사람의 점수를 비교하는 부분이 있기 때문에 완호의 두 점수를 더하여 wanhoScore에 완호의 총점을 넣었다.

 

 

이후 scores 배열을 0열을 내림차순 한 후, 1열을 오름차순을 하도록 했다.

 

 

가장 왼쪽에 있는 첫 행은 [근무 태도 점수, 동료 평가 점수] 중 동료 평가 점수가 낮아도 근무 태도 점수가 클 것이므로 해당 첫 행의 두 점수를 합친 수가 완호의 총점보다 높은지 비교하여 최종 답이 들어갈 변수를 증가시키거나 유지한다.

 

 

이후 반복문에서는 첫 행을 시작으로 왼쪽 행을 비교 대상으로 삼아 오른쪽 행의 동료 평가 점수 (1열) 이 크거나 같을 때 해당 항은 왼쪽 항의 근무 태도 점수에 관계 없이 크므로 무조건 인센티브를 받을 수 있는 사람의 점수이다.

 

따라서 이 조건에 해당이 되어 인센티브를 받을 수 있는 사람 중에 두 점수의 합 [근무 태도 점수, 동료 평가 점수]이 wanhoScore(완호의 총점)보다 높으면 답이 담길 변수를 증가시킨다.

 

이 조건에 해당이 되지 않을 경우에는 인센티브를 받을 수 없는 사람이 된다.

이 때 이 인센티브를 받지 못할 사람이 완호인 경우에는 정답 변수를 -1로 초기화하고, 반복문을 끝낼 수 있도록 break를 걸어주었다.

 

 

반복문이 끝난 이후에는 최종 답이 -1가 아닐 경우에는 반복문에서 완호 앞의 사람들만 세었기 때문에 완호의 최종 등수를 구하기 위해서는 최종 답의 변수를 1 증가시킨다.

 

 

여기서 틀린 이유는 인센티브를 받을 수 없는 사원 뒤에 나오는 사원이 인센티브를 받을 수 없는 사원과 똑같은 점수를 받았을 때 뒤에 나오는 사원은 인센티브를 받을 수 있도록 해당 코드가 돌아가기 때문인 것 같다.

 

수정한 코드

import java.util.Arrays;

class Solution {
    public int solution(int[][] scores) {
        int answer = 0;
        
        int[] wanho = scores[0];
        int wanhoScore = wanho[0] + wanho[1];
        boolean flag = true;
        int num = 0;

        Arrays.sort(scores, (o1, o2) -> o2[0] - o1[0]);
        Arrays.sort(scores, (o1, o2) -> {
            if (o1[0] == o2[0]) {
                return o1[1] - o2[1];
            }
            return 0;
        });

        if (scores[0][0] + scores[0][1] > wanhoScore) {
            answer++;
        }

        for (int i = 0; i < scores.length - 1; i++) {
            if (scores[i][0] == scores[i + 1][0] || scores[i][1 - num] <= scores[i + 1][1]) {
                if (flag && scores[i + 1][0] + scores[i + 1][1] > wanhoScore) {
                    answer++;
                }
                flag = true;
                num = 0;
            } else {
                flag = false;
                num++;
                if (scores[i + 1][0] == wanho[0] && scores[i + 1][1] == wanho[1]) {
                    answer = -1;
                    break;
                }
            }
        }
        if(answer!=-1){
            answer++;
        }
        
        return answer;
    }
}

 

flag를 넣어서 이전에 나온 점수를 가진 사람이 인센티브를 받을 수 없을 때 그 마지막으로 인센티브를 받은 사람과 비교하도록 만들고 싶었는데 잘 안된 것 같다. 런타임 오류도 있었고 실패도 많았다.

 

다시 문제를 풀어봐야 될 것 같다.

두 열을 서로 다르게 정렬한 이유가 단순히 오른족과 왼쪽을 비교해서 답을 구하기 위해서인지 다시 생각해야 된다.

예제를 [ 내림차순, 오름차순 ] 으로 정렬하면 [[3, 2], [3, 2], [2, 1], [2, 2], [1, 4]]이다.

이 때 왼쪽은 거의 고려하지 않으므로 오름차순으로 정렬된 동료 평가 점수를 기준으로 살펴보도록 하자.

동료 평가 점수만 보면 [2, 2, 1, 2, 4]이다.

이 때 인센티브를 받을 수 없는 사람은 가운데에 있는 1이다.

순서대로 인센티브를 받을 수 있는 사람은 [2, 2, 2, 4] 이다.

오름차순으로 정렬됐기 때문에 중간에 오름차순에서 벗어나게 되면 인센티브를 받을 수 없는 게 되는 것 같다.

그럼 maxScore 변수를 만들어 해당 수보다 크거나 같으면 인센티브를 지급하고 해당 수를 maxScore로 변화시켜도 될 것 같다.

 

최종 코드

import java.util.Arrays;

class Solution {
    public int solution(int[][] scores) {
        int answer = 0;
        
        int[] wanho = scores[0];
        int wanhoScore = wanho[0] + wanho[1];
        int maxScore = 0;

        Arrays.sort(scores, (o1, o2) -> o2[0] - o1[0]);
        Arrays.sort(scores, (o1, o2) -> {
            if (o1[0] == o2[0]) {
                return o1[1] - o2[1];
            }
            return 0;
        });

        for (int i = 0; i < scores.length; i++) {
            if (maxScore <= scores[i][1]) {
                maxScore = scores[i][1];
                if (scores[i][0] + scores[i][1] > wanhoScore) {
                    answer++;
                }
            } else {
                if (scores[i][0] == wanho[0] && scores[i][1] == wanho[1]) {
                    answer = -1;
                    break;
                }
            }
        }
        
        if(answer!=-1){
            answer++;
        }
        
        return answer;
    }
}

 

maxScore를 이용해 위에 적은 방식으로 코드를 다시 짜보니 바로 통과가 되었다.

내가 너무 복잡하게 생각한 건지 너무 단순하게 생각한 건지 만든 코드가 생각보다 너무 단순해서 화가 났다.

이렇게 단순하게 만들 수 있는 코드를 내가 얼마나 복잡하게 만든 건지 내가 너무 멍청하다...