[2021 KAKAO BLIND RECRUITMENT] 순위 검색

최민길(Gale)·2023년 4월 14일
1

알고리즘

목록 보기
67/172

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/72412

이 문제는 HashMap과 이진 탐색을 이용하여 풀 수 있습니다. 문제에서 주어진 info값을 하나의 문자열로 만들어 키로 Map에 추가합니다. 이 때 value값은 점수가 됩니다. 같은 조건일 때 여러 점수가 나올 수 있으므로 점수는 List로 추가합니다. 또한 문제 조건에서 -의 경우 모든 조건이므로 이 부분을 재귀함수를 이용하여 같이 추가해줍니다.

조건을 만족시키는 수를 더 빠르게 탐색하기 위해 이진 탐색을 진행합니다. 이를 위해 List를 오름차순으로 정렬을 먼저 진행합니다. min을 0, max를 List의 최대 인덱스로 설정한 후 mid를 계산하여 mid가 가리키는 점수가 요구하는 점수보다 작다면 min 값을 올리고 크다면 max값을 줄이는 식으로 계산합니다. 이 때 기준 점수보다 더 높은 점수의 수를 구해야 하므로 List의 전체 길이에서 구한 값을 뺀 값을 리턴해야 합니다.

다음은 코드입니다.

import java.util.*;

class Solution {
    static HashMap<String, List<Integer>> map = new HashMap<>();
    
    public int[] solution(String[] info, String[] query) {
        // map에 데이터 추가
        for(int i=0;i<info.length;i++){
            String[] arr = info[i].split(" ");
            setMap(arr, "", 0);
        }
        
        // 이분 탐색을 위한 map 데이터 정렬
        for(String key : map.keySet()){
            Collections.sort(map.get(key));
        }
        
        // 이분 탐색 진행
        int[] answer = new int[query.length];
        for(int i=0;i<query.length;i++){
            String str = query[i].replace(" and "," ");
            String[] arr = str.split(" ");
            StringBuilder sb = new StringBuilder();
            for(int j=0;j<arr.length-1;j++)
                sb.append(arr[j]);
            
            if(map.containsKey(sb.toString()))
                answer[i] = binarySearch(sb.toString(), Integer.parseInt(arr[arr.length-1]));
            else answer[i] = 0;
        }
        
        return answer;
    }
    
    // 기준 점수를 빠르게 탐색하기 위해 이진 탐색 사용
    static int binarySearch(String key, int score){
        List<Integer> val = map.get(key);
        int min = 0;
        int max = val.size()-1;
        
        while(min <= max){
            int mid = (min+max)/2;
            if(val.get(mid) < score) min = mid+1;
            else max = mid-1;
        }
        
        // 기준값보다 더 큰 점수들만 뽑아야 하므로 val.size()에서 min값을 뺀 값을 리턴
        return val.size()-min;
    } 
    
    static void setMap(String[] arr, String str, int depth){
        if(depth == 4){
            if(!map.containsKey(str)){
                map.put(str,new ArrayList<>());
            }
            map.get(str).add(Integer.parseInt(arr[4]));
            return;
        }
        
        // 현재 조건 대입
        setMap(arr, str+arr[depth], depth+1);
        
        // - 대입
        setMap(arr, str+"-", depth+1);
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글