문제
- 문제 링크
- 문제 설명: 지원자가 지원서에 입력한 4가지의 정보(개발언어, 직군, 경력, 소울푸드)와 획득한 코딩테스트 점수를 하나의 문자열로 구성한 값의 배열 info, 개발팀이 궁금해하는 문의조건이 문자열 형태로 담긴 배열 query가 매개변수로 주어질 때, 각 문의조건에 해당하는 사람들의 숫자를 순서대로 배열에 담아 반환하는 함수 작성
- 입력
- info 배열의 크기는 1 이상 50,000 이하
- 개발언어는 cpp, java, python 중 하나
- 직군은 backend, frontend 중 하나
- 소울푸드는 chicken, pizza 중 하나
- 점수는 코딩테스트 점수를 의미하며, 1 이상 100,000 이하인 자연수
- query 배열의 크기는 1 이상 100,000 이하
- query의 각 문자열은 "[조건] X" 형식
- '-' 표시는 해당 조건을 고려하지 않겠다는 의미
- X는 코딩테스트 점수를 의미하며 조건을 만족하는 사람 중 X점 이상 받은 사람은 모두 몇 명인 지를 의미
- 출력: 매 query마다 조건을 만족하는 사람 수를 배열에 담아 반환
info | query | result |
["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", "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"] |
[1,1,1,1,2,4] |
풀이
- query 배열의 크기가 최대 10만이기 때문에 매 쿼리에 info 배열을 순회하는 것은 시간초과가 발생한다. 따라서 O(logN) 으로 조건을 만족하는 사람을 찾도록 info 배열을 전처리 해주어야 한다.
- logN 의 시간으로 탐색하는 방법은 이진 탐색이 있다. 이진 탐색은 탐색 대상이 오름차순으로 정렬되었음을 가정한다.
- 4가지 지원자의 정보로 조합 가능한 조건들은 최대 (3+1) * (2+1) * (2+1) * (2+1) = 4 * 3 * 3 * 3 = 108가지이다. 1을 더한 것은 '-'을 포함한 것이다.
- map<string, vector<int>> 자료형을 이용해서 108가지의 조건 각각을 키로 가지고 조건에 해당되는 지원자의 점수를 값으로 가지게 하면 정렬 후 이진 탐색으로 원소의 위치를 알아내서 컨테이너 끝하고 오프셋으로 사람 수를 계산할 수 있게 된다.
- 시간 절약을 위해 unordered_map 을 활용하기로 했다.
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <unordered_map>
#include <algorithm>
using namespace std;
// 각 조건과 해당되는 점수 목록을 저장할 자료구조
unordered_map<string, vector<int>> m;
// 지원자 정보로 가능한 조건을 조합
void dfs(int pos, vector<string>& key, int& score, string s) {
if (pos == key.size()) {
m[s].push_back(score); // 생성된 조건마다 지원자의 점수 저장
return;
}
dfs(pos + 1, key, score, s + key[pos]);
dfs(pos + 1, key, score, s + "-");
}
vector<int> solution(vector<string> info, vector<string> query) {
vector<int> answer;
vector<string> key(4);
int score;
for (auto& i : info) {
istringstream iss(i);
iss >> key[0] >> key[1] >> key[2] >> key[3] >> score;
dfs(0, key, score, ""); // 가지고 있는 조건들로 가능한 조건 조합을 생성
}
for (auto it = m.begin(); it != m.end(); it++)
sort(it->second.begin(), it->second.end()); // 각 조건마다 지원자의 점수들을 오름차순 정렬
for (auto& q : query) {
istringstream iss(q);
string tmp; // and
iss >> key[0] >> tmp >> key[1] >> tmp >> key[2] >> tmp >> key[3] >> score;
auto it = m.find(key[0] + key[1] + key[2] + key[3]);
if (it == m.end()) answer.push_back(0); // 없는 조건이면 0명
else { // 있는 조건이면 이진 탐색으로 오프셋 계산
// lower_bound는 score보다 이상인 값들 중 가장 작은 값(하한)의 위치를 반환
auto vit = lower_bound(it->second.begin(), it->second.end(), score);
int num_applicants = it->second.end() - vit;
answer.push_back(num_applicants);
}
}
return answer;
}
'Algorithm > Problem Solving' 카테고리의 다른 글
[구현] (프로그래머스 Lv 3) 자물쇠와 열쇠 (0) | 2021.04.24 |
---|---|
[DFS] (프로그래머스 Lv 2) 후보키 (0) | 2021.04.24 |
[DFS, Bit-Operation, Set] (프로그래머스 Lv 2) 메뉴 리뉴얼 (0) | 2021.04.24 |
[Brute-Force, String] (프로그래머스 Lv 2) 문자열 압축 (0) | 2021.04.24 |
Google Code Jam 2021 Qualification Round (0) | 2021.04.06 |