ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Programmers] 순위 검색 / ⭕
    Algorithm/Programmers 2024. 10. 8. 16:16
     

    프로그래머스

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

    programmers.co.kr

     

    1. 제출 코드 (3시간 20분 45초 / 맵, 정렬, 이분탐색)

    import java.util.*;
    
    class Solution {
        static String[] lang = {"cpp", "java", "python"};
        static String[] role = {"backend", "frontend"};
        static String[] career = {"junior", "senior"};
        static String[] dish = {"chicken", "pizza"};
        static Map<String, ArrayList<Integer>> m = new HashMap<>();
        static int cnt = 0;
        public int[] solution(String[] info, String[] query) {
            int[] answer = new int[query.length];
            
            Arrays.sort(info, (o1, o2) -> {
                String[] t1 = o1.split(" ");
                String[] t2 = o2.split(" ");
                return Integer.parseInt(t1[4]) - Integer.parseInt(t2[4]);
            });
            
            for(int i = 0; i < info.length; i++) {
                String[] t = info[i].split(" ");
                ArrayList<Integer> ta = m.get(t[0] + t[1] + t[2] + t[3]);
    
                if(ta == null) {
                    m.put(t[0] + t[1] + t[2] + t[3], new ArrayList<>(Arrays.asList(Integer.parseInt(t[4]))));
                } else {
                    ta.add(Integer.parseInt(t[4]));
                    m.put(t[0] + t[1] + t[2] + t[3], ta);
                }
            }
            
            for(int i = 0; i < query.length; i++) {
                String[] t = query[i].split(" and ");
                int score = Integer.parseInt(t[3].split(" ")[1]);
                t[3] = t[3].split(" ")[0];
                cnt = 0;
                backtracking(t, "", 0, score);
                answer[i] = cnt;
            }
    
            return answer;
        }
        
        public static int binarySearch(ArrayList<Integer> t, int score) {
            int left = 0;
            int right = t.size() - 1;
            int mid = 0;
            while(left <= right) {
                mid = (left + right) / 2;
                if(t.get(mid) < score) left = mid + 1;
                else if (t.get(mid) >= score) right = mid - 1;
            }
            return t.size() - left;
        }
        
        public static void backtracking(String[] t, String word, int idx, int score) {
            if(idx == 4) {
                ArrayList<Integer> temp = m.get(word);
                if(temp != null) {
                    cnt += binarySearch(temp, score);
                }
                return;
            }
            if(t[idx].equals("-")) {
                if(idx == 0) {
                    for(int i = 0; i < 3; i++) {
                        backtracking(t, word + lang[i], idx + 1, score);
                    }   
                } else if(idx == 1) {
                    for(int i = 0; i < 2; i++) {
                        backtracking(t, word + role[i], idx + 1, score);
                    }   
                } else if(idx == 2) {
                    for(int i = 0; i < 2; i++) {
                        backtracking(t, word + career[i], idx + 1, score);
                    }   
                } else {
                    for(int i = 0; i < 2; i++) {
                        backtracking(t, word + dish[i], idx + 1, score);
                    }   
                } 
            } else {
                backtracking(t, word + t[idx], idx + 1, score);
            }
        }
    }

     

     

    2. 구현 로직

    1. info와 query의 크기를 봤을 때, N^2의 시간 복잡도는 될 수 없었다. NlogN 이하의 시간 복잡도를 가져야 하기에 Map을 사용했다.
    2. info의 점수를 추후 이분 탐색에 활용하기 위해 정렬
    3. info의 원소를 탐색하면서 나올 수 있는 모든 조합을 map에 저장
      1. info[i]를 split하여 점수와 그 외의 값들을 분리
      2. 개발언어, 직군, 경력, 소울푸드를 합친 문자열을 key로 두고 value를 Arraylist를 만들어 삽입(이때, 위에서 정렬이 이뤄졌기에 오름차순으로 들어감)
    4. query도 마찬가지로 탐색을 하는데 점수와 그 외의 값들을 분리
    5. query를 통해 나올 수 있는 경우의 수를 모두 찾기 위해 bactracking 함수 실행
      1. 만약, 현재의 idx가 "-"라면 각 항목의 모든 원소가 나올 수 있으므로 for문을 통해 하나씩 대입
      2. 위 경우가 아니라면 현재의 word 값에 t[idx]를 더해서 다음 순서로 넘김
      3. idx == 4는 점수를 제외한 모든 항목이 입력될 경우를 나타내는데, 이때 word의 값을 map에서 검색하여 해당되는 점수들을 가져온다.
      4. 기존에는 for문을 이용해서 score보다 큰 값이 있다면 cnt를 +1 해줬는데 효율성을 통과하지 못했다.
      5. 다시 생각해보니, 모든 info가 동일한 값을 가지면 최악의 경우가 되고 이는 n^2의 시간복잡도가 나오게된다. 이를 해결하기 위해 이분탐색을 진행했다.
      6. 이분 탐색을 통해 나온 left는 score보다 작은 원소들이므로 t.size() - left를 통해 score보다 큰 값의 개수를 추출
      7. 이후, 모든 경우의 수에서 나오는 cnt를 더해서 query에 대한 정답 추출

     

    3. 회고

    • 처음부터 어떻게 구현을 할지 생각하고 진행하는 습관을 가져야할 거 같다.
Designed by Tistory.