문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/72412
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
💡 풀이
주어진 info 값과 query문을 하나씩 비교해서 풀었더니, 효율성 검사에서 통과하지 못했습니다. 시간초과가 발생한 것이죠.
따라서, info를 탐색해 매 info마다 가능한(포함될 수 있는) 모든 경우의 수를 map의 key로 넣고, value에는 점수를 넣어 query에서 탐색하는 방법을 이용합니다. 이때, query에서 제시한 점수 이상인 info들의 값을 구하기 때문에 이분 탐색을 이용합니다.
info 값 바꾸기
java backend junior pizza 150
위처럼 주어진 info의 값을 점수를 제외하고 공백이 없도록 아래와 같은 형태로 바꿔줍니다.
javabackendjuniorpizza 150
여기서 앞의 문장은 Key, 뒤의 점수는 Value가 됩니다.
for(int index = 0; index < info.length; index++) {
String[] information = info[index].split(" ");
makeQuery(information, "", 0);
}
...
void makeQuery(String[] information, String str, int depth) {
if(depth == 4) {
if(!allPossibleMap.containsKey(str)) {
List<Integer> list = new ArrayList<>();
allPossibleMap.put(str, list);
}
allPossibleMap.get(str).add(Integer.parseInt(information[depth]));
return;
}
makeQuery(information, str + "-", depth + 1);
makeQuery(information, str + information[depth], depth + 1);
}
이때, 재귀를 사용해 앞 단어부터 자신과 "-"를 반복하며 붙여 나갑니다. 그럼 Map에는 (" javabackendjuniorpizza", [150])와 같은 형태로 들어갈 것입니다.
그리고, 이 Map을 value인 점수 List를 오름차순으로 정렬해 줍니다.
for(String key : allPossibleMap.keySet()) {
Collections.sort(allPossibleMap.get(key));
}
query 값 바꾸기
Map의 key값과 같은 형태로 만들기 위해 주어진 모든 query들도 info와 같은 형태로 변경해줍니다.
query[index] = query[index].replaceAll(" and ", "");
String[] oneQuery = query[index].split(" ");
이때, oneQuery의 0번 index는 문자열, 1번 index는 점수가 될 것입니다.
이분 탐색
query에서 제시한 점수 이상을 선택하길 원하기 때문에, 이분 탐색을 이용합니다. 이미 info의 value 값을 오름차순으로 정렬해두었기 때문에 이분 탐색을 이용할 수 있습니다.
int binarySearch(String key, int score) {
List<Integer> list = allPossibleMap.get(key);
int start = 0;
int end = list.size() - 1;
while(start <= end) {
int mid = (start + end) / 2;
if(list.get(mid) < score){
start = mid + 1;
continue;
}
end = mid - 1;
}
return list.size() - start;
}
list.size() -start는 $(key에 해당하는 점수의 총 개수) - (점수보다 크거나 같은 값의 시작 index)$이기 때문에 해당 점수 이상의 값의 개수를 구할 수 있습니다.
전체 코드
전첵적인 코드는 다음과 같습니다.
import java.util.*;
class Solution {
Map<String, List<Integer>> allPossibleMap = new HashMap<>();
public int[] solution(String[] info, String[] query) {
for(int index = 0; index < info.length; index++) {
String[] information = info[index].split(" ");
makeQuery(information, "", 0);
}
for(String key : allPossibleMap.keySet()) {
Collections.sort(allPossibleMap.get(key));
}
int[] answer = replaceQuery(query);
return answer;
}
void makeQuery(String[] information, String str, int depth) {
if(depth == 4) {
if(!allPossibleMap.containsKey(str)) {
List<Integer> list = new ArrayList<>();
allPossibleMap.put(str, list);
}
allPossibleMap.get(str).add(Integer.parseInt(information[depth]));
return;
}
makeQuery(information, str + "-", depth + 1);
makeQuery(information, str + information[depth], depth + 1);
}
int[] replaceQuery(String[] query) {
int[] result = new int[query.length];
for(int index = 0; index < query.length; index++) {
query[index] = query[index].replaceAll(" and ", "");
String[] oneQuery = query[index].split(" ");
if(allPossibleMap.containsKey(oneQuery[0])) {
result[index] = binarySearch(oneQuery[0], Integer.parseInt(oneQuery[1]));
continue;
}
result[index] = 0;
}
return result;
}
int binarySearch(String key, int score) {
List<Integer> list = allPossibleMap.get(key);
int start = 0;
int end = list.size() - 1;
while(start <= end) {
int mid = (start + end) / 2;
if(list.get(mid) < score){
start = mid + 1;
continue;
}
end = mid - 1;
}
return list.size() - start;
}
}
'알고리즘 > 프로그래머스' 카테고리의 다른 글
[Programmers] Level 3 : 길 찾기 게임 (1) | 2024.06.10 |
---|---|
[Programmers] Level 3 : 단어 변환(Java) (0) | 2024.04.02 |
[프로그래머스] Level 2 : 이모티콘 할인행사(Java) (0) | 2023.10.25 |
[프로그래머스] Level 2 : N-Queen(Java) (1) | 2023.10.23 |
[프로그래머스] Level 3 : 합승 택시 요금(Java) (4) | 2023.10.17 |