본문 바로가기
Algorithm

[Java]프로그래머스 - 인사고과

by brother_stone 2024. 1. 20.

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

최초 코드

import java.util.*;

class Solution {
    private int[] biggestA={0,0};
    private int[] biggestB={0,0};

    public int solution(int[][] scores) {
        //1 
        calcBiggestOne(scores);

        //2. enQueue
        PriorityQueue<Score> pq = new PriorityQueue<>();
        for(int i=0; i<scores.length; i++){
            if(i==0){
                if(!isValid(scores[i][0], scores[i][1])){
                    return -1;
                }
                pq.offer(new Score(scores[i][0],scores[i][1],true));
                continue;
            }

            if(!isValid(scores[i][0], scores[i][1])){
                continue;
            }
            pq.offer(new Score(scores[i][0],scores[i][1],false));
        }

        //3
        return calcRank(pq);
    }

    private void calcBiggestOne(int[][] scores){
        for(int i=0; i<scores.length; i++){
            if(scores[i][0]>biggestA[0]){
                biggestA=scores[i];
            }
            if(scores[i][1]>biggestB[1]){
                biggestB=scores[i];
            }
        }
    }

    private int calcRank(PriorityQueue<Score> pq){
        int cnt=0;
        int rank=0;
        Score prev=new Score(-1,-1,false);

        while(!pq.isEmpty()){
            Score polled = pq.poll();
            cnt++;

            if(polled.a+polled.b!=prev.a+prev.b){
                rank=cnt;
            }
            prev = polled;

            if(polled.isWonho){
                return rank;
            }

        }
        throw new IllegalArgumentException();
    }

    private boolean isValid(int currentA, int currentB){
        if(currentA<biggestA[0]){
            if(currentB<biggestA[1]){
                return false;
            }
        }

        if(currentB<biggestB[1]){
            if(currentA<biggestB[0]){
                return false;
            }
        }

        return true;
    }

    class Score implements Comparable<Score>{
        int a;
        int b;
        boolean isWonho;

        Score(int a, int b, boolean isWonho){
            this.a=a;
            this.b=b;
            this.isWonho=isWonho;
        }

        @Override
        public int compareTo(Score o){
            return (o.a+o.b)-(this.a+this.b);
        }
        }

    }
}

시나리오
0. a(근무 태도) + b(동료 평가)를 기준으로 내림차순 정렬이 되도록 compareTo를 구현하는 Score클래스를 만든다.

  1. 근무 태도가 가장 큰 사원을 biggestA에 저장, 동료 평가가 가장 큰 사원을 biggestB에 저장한다.
  2. biggestA와 biggestB보다 두 점수 모두가 작지 않은 사원을 PriorityQueue에 enQueue한다.(얘가 엣지케이스 원인인듯)
  3. 원호가 몇 위인지 계산한다.
    위 시나리오를 토대로 우선순위 큐를 이용해 풀어보려 했지만 아무리 개선해도 56점 까지 밖에 끌어올리지 못해 정답 코드를 구글링해보았다.
    아무래도 2번 시나리오에서 biggestA와 biggestB만을 비교대상으로 삼은게 문제인듯 하다. 이 친구를 고쳐서 정답을 도출해보자.

정답 코드

import java.util.Arrays;

class Solution {
    private Score[] scoreArr;

    public int solution(int[][] scores) {
        init(scores);
        return calcRank(new Score(scores[0][0],scores[0][1]));
    }

    private void init(int[][] scores){
        scoreArr = new Score[scores.length];

        for(int i=0; i<scores.length; i++){
            scoreArr[i] = new Score(scores[i][0], scores[i][1]);
        }

        Arrays.sort(scoreArr);
    }

    private int calcRank(Score wanho){
        int maxPeer=0;
        int rank=1;

        for(Score e : scoreArr){
            if(maxPeer > e.peer){
                if(wanho.equals(e)){
                    return -1;
                }
                continue;
            }
            maxPeer = Math.max(maxPeer, e.peer);
            if(wanho.getSum()<e.getSum()){
                rank++;
            }
        }

        return rank;
    }

    class Score implements Comparable<Score>{
        int attitude;
        int peer;

        Score(int attitude, int peer){
            this.attitude=attitude;
            this.peer=peer;
        }

        @Override
        public int compareTo(Score o){
            if(o.attitude==this.attitude){
                return this.peer - o.peer;
            }
            return o.attitude-this.attitude;
        }

        public boolean equals(Score o){
            return this.attitude==o.attitude&&this.peer==o.peer;
        }

        public int getSum(){
            return this.attitude+this.peer;
        }
    }
}

시나리오

  1. 근무 태도를 기준으로 내림차순 정렬 하되, 태도 점수가 같은 경우에 한해 동료 평가 점수로 오름차순 정렬하도록 compareTo를 구현한 Score클래스를 만든다.
  2. Score타입 배열에 기존 배열 scores요소를 삽입한다.
  3. 완호의 랭크를 계산. 우선 scoreArr변수를 순회하며 최대 동료평가 점수 보다 현재 사원의 동료평가 점수가 더 크면 최대 동료평가 점수를 갱신한다. 만약 완호의 점수 합보다 현재 사원의 점수 합이 더 큰 경우에만 rank++해준다. 완호보다 낮은 점수를 굳이 연산할 필요가 없기 때문이다. 이에 해당하지 않고 현재 사원의 동료평가 점수가 최대 동료평가 점수보다 작으면 인센티브를 받을 수 없는 사원이므로 연산에서 제외한다. 이유는 근무태도를 기준으로 내림차순 돼있는데 최대 동료 평가 점수보다 현재 동료평가 점수가 작다면, 현재 사원은 근무태도 점수, 동료평가 점수 모두 이전보다 작은 것이 되기 때문이다. 이 때 현재 사원이 완호라면 완호 또한 인센티브를 받을 수 없는 것이므로 return -1해준다.