ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 카카오 블라인드 2021) 순위 검색
    알고리즘/프로그래머스 카카오 2021. 3. 7. 18:07
    반응형

    순위 검색

     

    코딩테스트 연습 - 순위 검색

    ["java backend junior pizza 150","python frontend senior chicken 210","python frontend senior chicken 150","cpp backend senior pizza 260","java backend junior chicken 80","python backend senior chicken 50"] ["java and backend and junior and pizza 100","pyt

    programmers.co.kr

     

    이 문제도 여러 시도를 통해 풀었다.

    처음에 시도했던 것은, 문제의 조건에 따라 모두 파싱한 후, 값을 담을 class를 선언하여 인스턴스를 생성했었다. 이후, 각 조건들과 default인 조건에 따라 HashMap에 저장을 해주었는데, HashMap의 제네릭이 HashMap이고, 계속 타고 내려가다보니 로직이 복잡해졌었다.

    더 좋은 방법이 없을까 고민하다가, 다른 분의 풀이를 보니 default인 경우와 주어진 경우를 조합해서 key값으로 저장하는 방법이었다.

     

    문제에서 주어진 조건을 split한 이후, default를 포함한 경우를 for문을 통해 조합해주며 key 값을 만들어주었다.

    이 때, 이중 반복문을 통해 값을 저장해주는데, 비트 연산을 통해 조건에 부합하는 key 값을 생성해서 넣어주었다. (default -는 공백으로 처리한다.)

     

    모든 값을 조건에 따라 저장했으면, 해당 key에 들어있는 value를 오름차순으로 정렬해준다.

    정렬 이후에는 각 쿼리에 해당하는 지원자들의 List를 받아와서, 몇 명이 조건에 부합하는지 구해주었다.

    구할 때는 카카오의 힌트인 lower bound를 사용해서, 가장 처음으로 나오는 합격 최저 점수의 인덱스를 전체 길이에서 빼주어 구했다. (list의 size - lower bound 결과 인덱스)

     

    저장할 때와, 소팅할 때, computeIfAbsent와 Entry를 사용해서 정렬할 수 있다는 것을 이 분의 풀이를 보고 내가 자바를 제대로 사용하지 못하고 있구나를 느꼈다.. 덕분에 자바에 대해 더 이해할 수 있었다.

     

    코드
    import java.util.*;
    
    public class Solution {
      final String DEFAULT = "-", QUERY_REGEX = " and ", SPACE = " ", NOTHING = "";
      final int CONDITION_LENGTH = 4;
      final int SCORE_INDEX = 4;
    
      public int[] solution(String[] info, String[] query) {
        Map<String, List<Integer>> map = getInfoMap(info);
        int len = query.length;
        int[] answer = new int[len];
    
        for(int i=0; i<len; i++) {
          answer[i] = getCounts(map, query[i]);
        }
    
        return answer;
      }
    
      private Map<String, List<Integer>> getInfoMap(String[] info) {
        HashMap<String,List<Integer>> map = new HashMap<>();
        final int MAX_CONDITION = 1 << CONDITION_LENGTH;
        for(String applicant : info) {
          String[] data = getCondition(applicant);
          int score = Integer.parseInt(data[SCORE_INDEX]);
    
          for(int i=0; i<MAX_CONDITION; i++) {
            StringBuilder sb = new StringBuilder();
            for(int j=0; j<CONDITION_LENGTH; j++) {
              if((i&(1 <<j)) >0) { // i: 1 ~> j: 0, i: 2 ~> j: 1, i: 3 ~> j:0,1 , i: 4 ~> j: 1,2 
                sb.append(data[j]); // => 조합 가능한 모든 경우를 만들어 key로 생성
              }
            }
            String key = sb.toString();
            map.computeIfAbsent(key, mappingFunction -> new ArrayList<>()).add(score);
          }
        }
    
        for(Map.Entry<String, List<Integer>> entry : map.entrySet()) {
          entry.getValue().sort(null);
        }
    
        return map;
      }
    
      private int getCounts(Map<String, List<Integer>> map, String query) {
        String[] queryCondition = getCondition(query.replaceAll(DEFAULT, NOTHING).replaceAll(QUERY_REGEX, SPACE));
        String key = getKey(queryCondition);
        int score = Integer.parseInt(queryCondition[SCORE_INDEX]);
        List<Integer> list = map.getOrDefault(key, new ArrayList<>());
    
        return list.size() - lowerBound(list, score);
      }
    
      private String[] getCondition(String condition) {
        return condition.split(SPACE);
      }
    
      private String getKey(String[] conditions) {
        StringJoiner sj = new StringJoiner(NOTHING);
        for(int i=0; i<CONDITION_LENGTH; i++) {
          sj.add(conditions[i]);
        }
        return sj.toString();
      }
    
      private int lowerBound(List list, int score) {
        int left =0, right = list.size();
    
        while(left < right) {
          int mid = (left + right) /2;
          if((int)list.get(mid) >= score) {
            right = mid;
          } else {
            left = mid+1;
          }
        }
        return left;
      }
    }

     

     

    Reference

    girawhale.tistory.com/94

    반응형

    댓글

Designed by Tistory.