프로그래머스 2021 KAKAO BLIND RECRUITMENT 순위 검색 [JAVA] - 22년 9월 3일

Denia·2022년 9월 3일
0

코딩테스트 준비

목록 보기
56/201

처음에 사용한 코드 [효율성 전부 실패 , 정확성만 통과]

info 의 조건들을 set으로 만들고, 해당 조건의 점수들을 List 로 만들어서 set 및 List 를 Key, Value로 하는 map 을 하나 생성
그 후에 query를 돌면서 해당하는 조건들을 set으로 만들어서 map에 해당 조건들이 있는지 확인하여 조건이 만족할때만 만족하는 점수들의 List를 가져와서 sort 후 lowerBound 메서드 적용후 갯수를 구함

package com.company;

import java.util.*;

class Solution {
    public int[] solution(String[] info, String[] query) {
        List<Integer> answer = new ArrayList<Integer>();
        Map<Set<String>, List<Integer>> map = new HashMap<>();
        for (String str : info) {
            int splitIndex = str.lastIndexOf(" ");
            String[] keys = str.substring(0, splitIndex).split(" ");
            Set<String> set = new HashSet<>(Arrays.asList(keys));

            Integer value = Integer.valueOf(str.substring(splitIndex + 1));
            List<Integer> list = map.getOrDefault(set, new ArrayList<>());
            list.add(value);
            map.put(set, list);
        }

        for (String str : query) {
            String[] queryStrings =  str.replace(" and ", " ").split(" ");
            int targetScore = Integer.parseInt(queryStrings[queryStrings.length - 1]);
            Set<String> set = new HashSet<>();

            for (int i = 0; i < queryStrings.length - 1; i++) {
                if(!queryStrings[i].equals("-")) set.add(queryStrings[i]);
            }
            
            List<Integer> valueList = new ArrayList<>();
            for (Set<String> eachKeySet : map.keySet()) {
                if(eachKeySet.containsAll(set)){
                    valueList.addAll(map.get(eachKeySet));
                }
            }

            valueList.sort(null);

            int targetNum = bisectLeft(valueList,targetScore);
            answer.add(valueList.size() - targetNum);
        }


        return answer.stream().mapToInt(Integer::intValue).toArray();
    }

    private int bisectLeft(List<Integer> valueList, int targetScore) {
        int start = 0;
        int end = valueList.size();

        while (start < end){
            int mid = (start + end) / 2;
            if(valueList.get(mid) >= targetScore){
                end = mid;
            }else{
                start = mid + 1;
            }
        }

        return end;
    }
}

정답 코드 참조하여 수정[동일한 query가 반복될 경우에도 중복 sorting이 발생하지 않으므로 시간을 단축]

정답 참조 사이트 : https://school.programmers.co.kr/questions/29190

info를 순회하면서 가능한 모든 조합에 점수를 넣기 -> 점수들이 들어있는 ArrayList 전체를 정렬하기 -> query를 순회하면서 점수보다 높은 사람들 수 구하기 이런 로직으로 해결

※주의할점 : 테스트케이스 query 중에는 전혀 info에 맞지 않는 이상한 조건들로 된 경우도 존재하며 그럴때는 map에서 해당 key 를 찾지못해서 List<Integer>가 null이 나올수도 있다. 이럴 경우 예외처리를 잘 해줘야 한다.

package com.company;

import java.util.*;

class Solution {
    String[] gInfo;
    Map<String, List<Integer>> map;
    public int[] solution(String[] infos, String[] query) {
        List<Integer> answer = new ArrayList<Integer>();
        map = new HashMap<>();
        for (String info : infos) {
            gInfo = info.split(" ");
            dfs("",0);
        }

        for (List<Integer> list : map.values()) {
            list.sort(null);
        }

        for (String str : query) {
            String editStr = str.replace(" and ", "");
            int splitIndex =  editStr.lastIndexOf(" ");
            int targetScore = Integer.parseInt(editStr.substring(splitIndex + 1));
            String targetStr = editStr.substring(0, splitIndex);

            List<Integer> valueList = map.getOrDefault(targetStr, new ArrayList<>());

            int targetNum = bisectLeft(valueList,targetScore);
            answer.add(valueList.size() - targetNum);

        }

        return answer.stream().mapToInt(Integer::intValue).toArray();
    }

    private void dfs(String str , int index) {
        if(index == 4){
            List<Integer> list = map.getOrDefault(str, new ArrayList<>());
            list.add(Integer.valueOf(gInfo[index]));
            map.put(str, list);
            return;
        }

        String tempStr1 = str + gInfo[index];
        dfs(tempStr1,index + 1);
        String tempStr2 = str + "-";
        dfs(tempStr2,index + 1);
    }

    private int bisectLeft(List<Integer> valueList, int targetScore) {
        int start = 0;
        int end = valueList.size();

        while (start < end){
            int mid = (start + end) / 2;
            if(valueList.get(mid) >= targetScore){
                end = mid;
            }else{
                start = mid + 1;
            }
        }

        return end;
    }
}

profile
HW -> FW -> Web

0개의 댓글