🖊️ 문제
[본 문제는 정확성과 효율성 테스트 각각 점수가 있는 문제입니다.]
카카오는 하반기 경력 개발자 공개채용을 진행 중에 있으며 현재 지원서 접수와 코딩테스트가 종료되었습니다. 이번 채용에서 지원자는 지원서 작성 시 아래와 같이 4가지 항목을 반드시 선택하도록 하였습니다.
- 코딩테스트 참여 개발언어 항목에 cpp, java, python 중 하나를 선택해야 합니다.
- 지원 직군 항목에 backend와 frontend 중 하나를 선택해야 합니다.
- 지원 경력구분 항목에 junior와 senior 중 하나를 선택해야 합니다.
- 선호하는 소울푸드로 chicken과 pizza 중 하나를 선택해야 합니다.
인재영입팀에 근무하고 있는 니니즈는 코딩테스트 결과를 분석하여 채용에 참여한 개발팀들에 제공하기 위해 지원자들의 지원 조건을 선택하면 해당 조건에 맞는 지원자가 몇 명인 지 쉽게 알 수 있는 도구를 만들고 있습니다.
예를 들어, 개발팀에서 궁금해하는 문의사항은 다음과 같은 형태가 될 수 있습니다.
코딩테스트에 java로 참여했으며, backend 직군을 선택했고, junior 경력이면서, 소울푸드로 pizza를 선택한 사람 중 코딩테스트 점수를 50점 이상 받은 지원자는 몇 명인가?
물론 이 외에도 각 개발팀의 상황에 따라 아래와 같이 다양한 형태의 문의가 있을 수 있습니다.
- 코딩테스트에 python으로 참여했으며, frontend 직군을 선택했고, senior 경력이면서, 소울푸드로 chicken을 선택한 사람 중 코딩테스트 점수를 100점 이상 받은 사람은 모두 몇 명인가?
- 코딩테스트에 cpp로 참여했으며, senior 경력이면서, 소울푸드로 pizza를 선택한 사람 중 코딩테스트 점수를 100점 이상 받은 사람은 모두 몇 명인가?
- backend 직군을 선택했고, senior 경력이면서 코딩테스트 점수를 200점 이상 받은 사람은 모두 몇 명인가?
- 소울푸드로 chicken을 선택한 사람 중 코딩테스트 점수를 250점 이상 받은 사람은 모두 몇 명인가?
- 코딩테스트 점수를 150점 이상 받은 사람은 모두 몇 명인가?
즉, 개발팀에서 궁금해하는 내용은 다음과 같은 형태를 갖습니다.
* [조건]을 만족하는 사람 중 코딩테스트 점수를 X점 이상 받은 사람은 모두 몇 명인가?
지원자가 지원서에 입력한 4가지의 정보와 획득한 코딩테스트 점수를 하나의 문자열로 구성한 값의 배열 info, 개발팀이 궁금해하는 문의조건이 문자열 형태로 담긴 배열 query가 매개변수로 주어질 때,
각 문의조건에 해당하는 사람들의 숫자를 순서대로 배열에 담아 return 하도록 solution 함수를 완성해 주세요.
🖥️ 코드
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <map>
using namespace std;
vector<int> solution(vector<string> info, vector<string> query)
{
vector<int> answer;
vector<int> db[3][2][2][2];
map<string, int> m;
m["-"] = -1;
m["cpp"] = 0;
m["java"] = 1;
m["python"] = 2;
m["backend"] = 0;
m["frontend"] = 1;
m["junior"] = 0;
m["senior"] = 1;
m["chicken"] = 0;
m["pizza"] = 1;
for(int i = 0; i < info.size(); i++)
{
stringstream ss(info[i]);
string a, b, c, d, e;
ss >> a >> b >> c >> d >> e;
db[m[a]][m[b]][m[c]][m[d]].push_back(stoi(e));
}
for(int i = 0; i < 3; i++)
for(int j = 0; j < 2; j++)
for(int k = 0; k < 2; k++)
for(int l = 0; l < 2; l++)
sort(db[i][j][k][l].begin(), db[i][j][k][l].end(), greater<int>());
for(int i = 0; i < query.size(); i++)
{
stringstream ss(query[i]);
string a, b, c, d, e, dummy;
int la, pos, cr, fd, score, res = 0;
ss >> a >> dummy >> b >> dummy >> c >> dummy >> d >> e;
la = m[a], pos = m[b], cr = m[c], fd = m[d], score = stoi(e);
for(int j = 0; j < 3; j++)
{
if(la != -1 && la != j) continue;
for(int k = 0; k < 2; k++)
{
if(pos != -1 && pos != k) continue;
for(int l = 0; l < 2; l++)
{
if(cr != -1 && cr != l) continue;
for(int m = 0; m < 2; m++)
{
if(fd != -1 && fd != m) continue;
for(int n = 0; n < db[j][k][l][m].size(); n++)
{
if(db[j][k][l][m][n] >= score) res++;
else break;
}
}
}
}
}
answer.push_back(res);
}
return answer;
}
🤔 나의 생각
조건을 고려하지 않는 -를 똑똑하게 처리해 보려고 노력했는데 생각이 안 나서 그냥 중첩 for를 돌렸다...
조건을 조합하는 경우의 수가 적어서 중첩 for를 사용했지만 조금 더 스마트한 방법이 필요한 것 같아 다른 사람의 풀이를 참고해서 새로 풀어봤다.
비트 연산자 사용 풀이
비트 연산자로 -가 포함되는 모든 경우의 수를 계산해서 미리 db 벡터에 넣어주는 코드이다.
예를 들어 지원자 정보 java backend junior pizza를 파싱 하면
[2, 1, 1, 2]이 된다.여기서 라인 34의 j가 1일 때를 생각해 보면, 1은 2진수로 0001로 k for문을 돌며 -가 포함되는 조건을 [2, 0(-), 0(-), 0(-)] db에 저장하게 된다.
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <map>
using namespace std;
vector<int> solution(vector<string> info, vector<string> query)
{
vector<int> answer;
vector<int> db[4][3][3][3];
map<string, int> m;
m["-"] = 0;
m["cpp"] = 1;
m["java"] = 2;
m["python"] = 3;
m["backend"] = 1;
m["frontend"] = 2;
m["junior"] = 1;
m["senior"] = 2;
m["chicken"] = 1;
m["pizza"] = 2;
for (int i = 0; i < info.size(); i++)
{
stringstream ss(info[i]);
string a, b, c, d;
int score;
ss >> a >> b >> c >> d >> score;
vector<int> v = { m[a], m[b], m[c], m[d] };
for (int j = 0; j < 16; j++)
{
vector<int> idxs(4, 0);
for (int k = 0; k < 4; k++)
if (j & (1 << k))
idxs[k] = v[k];
db[idxs[0]][idxs[1]][idxs[2]][idxs[3]].push_back(score);
}
}
for (int i = 0; i < 4; i++)
for (int j = 0; j < 3; j++)
for (int k = 0; k < 3; k++)
for (int l = 0; l < 3; l++)
sort(db[i][j][k][l].begin(), db[i][j][k][l].end(), less<int>());
for (int i = 0; i < query.size(); i++)
{
stringstream ss(query[i]);
string a, b, c, d, dummy;
int res = 0, score;
ss >> a >> dummy >> b >> dummy >> c >> dummy >> d >> score;
vector<int>& v = db[m[a]][m[b]][m[c]][m[d]];
auto iter = lower_bound(v.begin(), v.end(), score);
answer.push_back(v.end() - iter);
}
return answer;
}
중요한 건 -가 포함되는 조건을 db에 다 넣었기 때문에 단순 for문을 돌며 x점 이상을 받은 사람들의 수를 구하면 시간 초과가 나는 듯하다. 많은 사람들이 정답 도출을 위해 이진 탐색을 이용했다. 이진 탐색에서 파생된 lower_bound는 찾는 값 이상이 처음으로 나오는 원소의 반복자를 반환한다.
+ 실제 이진 탐색은 binary_search로 구현되어 있다.
비트 연산자를 이렇게 쓸 수 있음을 배워나갔다~!
'Algorithm > 프로그래머스 : Level 2' 카테고리의 다른 글
[프로그래머스 Level 2] 위장 (0) | 2021.11.18 |
---|---|
[프로그래머스 Level 2] 괄호 회전하기 (0) | 2021.11.18 |
[프로그래머스 Level 2] 타겟 넘버 (0) | 2021.11.16 |
[프로그래머스 Level 2] 예상 대진표 (0) | 2021.11.16 |
[프로그래머스 Level 2] 기능 개발 (0) | 2021.11.15 |