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;
}
}
정답 참조 사이트 : 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;
}
}