안녕하세요. 오늘은 프로그래머스의 순위 검색 문제를 풀어보려고 합니다. 이 문제는 2021년 kakao blind recruitment에서 출제되었습니다.!
https://programmers.co.kr/learn/courses/30/lessons/72412
dfs와 이진탐색(binary search)를 이용하는 문제였습니다.
key가 String이고 value가 ArrayList인 해시맵을 선언한 후 dfs를 돌면서 해시맵에 모든 경우의 수를 채워줍니다.
예를 들어, info에 "java backend junior pizza 150"가 있으면, dfs를 돌면서 각 경우의 수에 따른 점수를 모두 저장합니다. 아래 표를 참고해주세요.
Key (String) | Value(ArrayList) |
---|---|
javabackendjuniorpizza | 150 |
javabackendjunior- | 150 |
javabackend-- | 150 |
java--- | 150 |
...... | ...... |
이런식으로 모든 경우의 수에 해당하는 key값들을 만들어주고, 각 value에는 지원자의 점수를 저장해주면 됩니다.
Dfs를 모두 수행하고 난 후, value에 저장된 점수들을 오름차순으로 정렬해줍니다. 해당 과정은 점수 이진탐색을 수행하기 위해 꼭 필요합니다.
query는 문의조건이 담겨있는 배열로, 각 문의조건에 해당하는 사람들의 수를 구해야 합니다. query배열에 있는 점수가 이진탐색을 통해 찾으려는 값이 되며, 2번 과정을 통해 정렬된 value들을 탐색하며 문의조건에 맞는 점수를 가진 사람이 몇 명인지 찾으면 됩니다.
import java.util.*;
class Solution {
HashMap<String, ArrayList<Integer>> map;
public int[] solution(String[] info, String[] query) {
int[] answer = new int[query.length];
map = new HashMap<>();
for (String str : info) {
String[] infoSpl = str.split(" ");
dfs("", 0, infoSpl);
}
ArrayList<String> list = new ArrayList<>(map.keySet());
//주소값 참조를 이용한 sort 처리
for (String str : list) {
ArrayList<Integer> scoreList = map.get(str);
Collections.sort(scoreList);
}
for (int i = 0; i < query.length; i++) {
String str = query[i].replaceAll(" and ", "");
String[] strSpl = str.split(" ");
answer[i] = binarySearch(strSpl[0], Integer.parseInt(strSpl[1]));
}
return answer;
}
private void dfs(String str, int depth, String[] arr) {
if (depth == 4) {
int score = Integer.parseInt(arr[4]);
if(map.containsKey(str)) map.get(str).add(score);
else {
ArrayList<Integer> list = new ArrayList<>();
list.add(score);
map.put(str, list);
}
return;
}
dfs(str + "-", depth + 1, arr);
dfs(str + arr[depth], depth + 1, arr);
}
private int binarySearch(String query, int score) {
if(!map.containsKey(query)) return 0;
ArrayList<Integer> list = map.get(query);
int left = 0, right = list.size()-1;
while (left <= right) {
int mid = (left + right) / 2;
if(score > list.get(mid)) left = mid + 1;
else right = mid - 1;
}
return list.size() - left;
}
}
혼자서는 전혀 풀이법을 생각하지 못했다. 또한, 인터넷에서 답을 찾아보고도 이해하기까지 꽤 오랜 시간이 걸렸다. 그만큼 dfs와 이진탐색을 익히기 좋은 문제라고 생각한다. 풀이법을 외워서 다음에 비슷한 문제가 나오면 맞도록 해야겠다.
[참고한 곳]