Problem_Solving
프로그래머스 : 순위 검색 (자바, 파이썬)
CONCAT
2024. 1. 25. 16:34
728x90
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
설계
- 브루트 포스로 가능한 모든 조건의 조합을 생성하고, 이진 탐색을 통해 효율적으로 해당 조건을 만족하는 지원자 수를 찾아냄
- 각 info 문자열에 대해 가능한 모든 조건의 조합을 생성하고, 해당 조건에 해당하는 점수를 Map에 저장
- Map의 각 값(점수 리스트)를 오름차순으로 정렬
- 각 query에 대해 해당 조건을 만족하는 점수의 개수를 찾기 위해 이진 탐색을 사용
- 이진 탐색을 통해 주어진 점수 조건을 만족하는 지원자의 수를 계산하여 결과 배열에 저장
구현
코드
자바(Java)
// package pg72412;
// https://school.programmers.co.kr/learn/courses/30/lessons/72412
import java.util.*;
import java.io.*;
// public class Main {
// public static void main(String[] args) {
// String[] info = { "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" };
// String[] query = { "java and backend and junior and pizza 100",
// "python and frontend and senior and chicken 200", "cpp and - and senior and pizza 250",
// "- and backend and senior and - 150", "- and - and - and chicken 100",
// "- and - and - and - 150" };
// Solution sol = new Solution();
// System.out.println(Arrays.toString(sol.solution(info, query)));
// }
// }
class Solution {
// 주어진 info와 query를 기반으로 쿼리에 해당하는 정보 개수를 반환하는 메서드
public int[] solution(String[] info, String[] query) {
int[] answer = new int[query.length];
Map<String, List<Integer>> map = new HashMap<>();
// info 문자열을 처리하여 가능한 모든 조합을 맵에 저장
for (String s : info) {
String[] str = s.split(" ");
int score = Integer.parseInt(str[4]);
generateCombinations(str, score, 0, "", map);
}
// 맵의 각 값(점수 리스트)를 정렬
for (Map.Entry<String, List<Integer>> entry : map.entrySet()) {
entry.getValue().sort(null);
}
// 쿼리 처리
for (int i = 0; i < query.length; i++) {
String[] str = query[i].replaceAll("-", "").split(" and | ");
int score = Integer.parseInt(str[4]);
String key = String.join("", str[0], str[1], str[2], str[3]);
List<Integer> list = map.getOrDefault(key, new ArrayList<>());
// 이진 탐색을 사용하여 점수 조건을 만족하는 개수 계산
int s = 0, e = list.size();
while (s < e) {
int mid = (s + e) / 2;
if (list.get(mid) < score) {
s = mid + 1;
} else {
e = mid;
}
}
answer[i] = list.size() - s;
}
return answer;
}
// 조합을 생성하고 맵에 저장하는 메서드
public void generateCombinations(String[] str, int score, int index, String current, Map<String, List<Integer>> map) {
if (index == str.length) {
map.computeIfAbsent(current, k -> new ArrayList<>()).add(score);
return;
}
// 현재 원소를 포함하는 경우
generateCombinations(str, score, index + 1, current + str[index], map);
// 현재 원소를 포함하지 않는 경우
generateCombinations(str, score, index + 1, current, map);
}
}
파이썬 (Python)
# from pprint import pprint
# info = ["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"]
# query = ["java and backend and junior and pizza 100",
# "python and frontend and senior and chicken 200",
# "cpp and - and senior and pizza 250",
# "- and backend and senior and - 150",
# "- and - and - and chicken 100",
# "- and - and - and - 150"]
# 주어진 info와 query를 기반으로 쿼리에 해당하는 지원자 수를 반환하는 함수
def solution(info, query):
# pprint(info) # 정보 출력 (디버깅용)
# pprint(query) # 쿼리 출력 (디버깅용)
answer = []
_map = {} # 각 조건에 해당하는 점수 리스트를 저장할 딕셔너리
# info 데이터 처리
for el in info:
*data, score = el.split() # 데이터 분리
recursive(data, score, 0, '', _map) # 가능한 모든 조합 생성
# 딕셔너리의 각 값(점수 리스트)를 정렬
for v in _map.values():
v.sort()
# 쿼리 처리
for i in range(len(query)):
*q, score = query[i].split() # 쿼리 분리
k = ''.join([v for v in q if v not in ['and', '-']]) # 필요한 조건만 추출
scores = _map.get(k, []) # 해당 조건에 맞는 점수 리스트 가져오기
answer.append(binary_search(int(score), scores)) # 이진 탐색으로 지원자 수 계산
return answer
# 조합을 생성하고 딕셔너리에 저장하는 함수
def recursive(data, score, index, current, _map):
if index == len(data):
if current not in _map:
_map[current] = []
_map[current].append(int(score))
return
recursive(data, score, index + 1, current + data[index], _map)
recursive(data, score, index + 1, current, _map)
# 이진 탐색을 수행하는 함수
def binary_search(score, scores):
left = 0
right = len(scores)
while left < right:
mid = (left + right) // 2
if scores[mid] < score:
left = mid + 1
else:
right = mid
return len(scores) - left
# 결과 출력
# pprint(solution(info, query))