ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 알고리즘) 프로그래머스 Graph, 순위
    알고리즘/프로그래머스 고득점 Kit 2020. 4. 27. 16:14
    반응형

    프로그래머스 고득점 Kit - Graph

    순위

     

    풀이

    (2020.04.27)

    문제의 조건에서 경기 결과에 모순이 없으며,  A>B, B>C 이면 항상 A>B>C의 순서가 매겨진다고 되어있다. 따라서, 경기 결과가 유실되어도 특정 선수(A)가 이긴 상대들은 A를 이긴 상대들이 이길 수 있다는 뜻이다. 경기 결과 입력 후, 서로 상관관계에 따라 입력을 해주고 랭킹을 부여할 수 있는 선수들을 찾아 return했다.

     

    1. 전체 경기 결과를 이긴 상대 리스트, 진 상대 리스트에 담아준다. (선수 Index에 맞춰서)

    2. 서로 경기 결과에 대해 이기고 진 상대들을 업데이트 해준다.

    3. 경기 결과가 모두 있는 선수들은 Rank를 부여할 수 있으므로, 전체 경기 결과가 있는 선수들의 수를 return해준다.

     

    (2020.06.04)

    리스트를 쓰지 않고, 배열을 통해 답을 구해주었다.

    처음 풀었을 때는 특정 선수가 이긴 선수들 List와 진 선수들 List를 만들어주어 확인했는데, 배열에 그냥 이기고 진 표시를 해주었다.

    이긴 경우에는 1로, 진 경우에는 -1로 값을 저장해주었다.

    경기 기록이 저장된 이후에는, 반복문을 통해 탐색하면서 두 가지 조건에 따라 값을 조정해주었다.

     

    1. 특정 선수가 다른 선수를 이긴경우

    2. 특정 선수가 다른 선수에게 진 경우

     

    1 번의 경우에는 내가 이긴 상대면, 상대가 이긴 선수들을 특정 선수가 이길 수 있다고 저장해주었다.

    2 번의 경우에는 내가 진 상대한테, 내가 이긴 선수들을 다 이길 수 있다고 저장해주었다.

    동시에 1번과 2번에서 지는 선수의 기록도 진다고 저장해주면서 경기 기록을 완성하였다.

     

    완성된 경기 기록을 돌면서 count를 통해, 몇 명이 랭크를 확정지을 수 있는지 세주었다.

     

    코드 1

     

    import java.util.LinkedList;
    
    public class KitGraphRank {
        private static int solution(int n, int[][] results) {
            LinkedList<Integer>[] winnerList = inItLinkedList(n);     //i가 이긴 선수들 List
            LinkedList<Integer>[] loserList = inItLinkedList(n);      //i가 진 선수들 List
    
            for(int[] game : results) {
                winnerList[game[0]].offer(game[1]);  // 선수가 이긴것만 저장
                loserList[game[1]].offer(game[0]); // 선수가 진것만 저장
            }
    
            for(int i=1; i<=n; i++) {
                winnerList = addMatches(winnerList, loserList, i, n);   // i 선수가 이기는 상대 선수 추가
                loserList = addMatches(loserList, winnerList, i, n);    // i 선수가 지는 상대 선수 추가
            }
    
            return getFixCount(winnerList, loserList, n);       // Rank 를 정할 수 있는 선수 수 return
        }
    
        private static int getFixCount(LinkedList<Integer>[] winnerList, LinkedList<Integer>[] loserList, int n) {
            int cnt=0;
            for(int i=1; i<=n; i++) {
                if(isAllMatches(winnerList[i], loserList[i], n)) { // 경기기록이 다 있으면
                    cnt++;
                }
            }
            return cnt;
        }
    
        private static boolean isAllMatches(LinkedList<Integer> winList, LinkedList<Integer> loseList, int n) { // 모든 경기기록 체크
            return winList.size() + loseList.size() == n-1 ? true : false;
        }
    
        private static LinkedList<Integer>[] inItLinkedList(int n) {    // InIt
            LinkedList<Integer>[] result = new LinkedList[n+1];
            for(int i=1; i<=n; i++) {
                result[i] = new LinkedList<>();
            }
            return result;
        }
    
        // 선수의 상관 관계를 업데이트 시켜줄 메소드
        private static LinkedList<Integer>[] addMatches(LinkedList<Integer>[] match1, LinkedList<Integer>[] match2, int player, int n) {
            //match1,match2가 서로 winList or loseList가 될 것임
            // match1이 WinnerList, match2가 loserList => i 선수가 이긴 선수들에게 진 선수들을 i선수가 이기는 선수들에 추가
            // 반대의 경우 => i선수가 진 선수들에게 이긴 선수들을 i 선수가 지는 선수들에 추가
            for(int origin : match2[player]) {    // match2에 담긴 player가 치룬 경기 정보를 받아와서
                for (int target : match1[player]) {  // match1에 담긴 player가 경기한 선수들
                    if (!match1[origin].contains(target)) {  // 중복 체크
                        match1[origin].offer(target);        // match2에서 겨룬 선수에대해 match1에 저장
                    }
                }
            }
            return match1;
        }
    
        public static void main(String[] args) {
            int n=5;
            int[][] result = {{4, 3}, {4, 2}, {3, 2}, {1, 2}, {2, 5}};
    
            System.out.println(solution(n, result));
        }
    }

     

    코드 2

     

    class Solution {
        public int solution(int n, int[][] results) {
            int answer = 0;
            int[][] matches = new int[n+1][n+1];
            for(int[] match : results) {
                matches[match[0]][match[1]] = 1; // 이김
                matches[match[1]][match[0]] = -1; // 짐
            }
            
            // match 저장
            for(int player=1; player<=n; player++) {
                for(int enemy =1; enemy<=n; enemy++) {
                    if(matches[player][enemy] ==1) {    // 내가 이긴 애들
                        for(int i=1; i<=n; i++) {   
                            if(matches[enemy][i] == 1) {    // 상대가 이긴 애들
                                matches[player][i] =1; // 나도 이김
                                matches[i][player] = -1;
                            }
                        }
                    } else if(matches[player][enemy] ==-1) {    // 내가 진 애들
                        for(int i=1; i<=n; i++) {  
                            if(matches[player][i] ==1) { // 내가 이긴애들 다 이겨
                                matches[enemy][i] =1;
                                matches[i][enemy] =-1;
                            }
                        }
                    }
                }
            }
            
            // count
            for(int y=1; y<=n; y++) {
                int cnt =0;
                for(int x=1; x<=n; x++) {
                    if(matches[y][x] !=0) {
                        cnt++;
                    }
                }
                if(cnt == n-1) {
                    answer++;
                }
            }
            
            return answer;
        }
    }
    반응형

    댓글

Designed by Tistory.