참고자료
이 문제는 구글링을 통해 해결하였으므로 참고한 블로그를 상단에 첨부합니다.
https://eunchanee.tistory.com/319
https://transferhwang.tistory.com/442 (비트 연산 이용하신 분! 코드가 더 간단)
📌순위 검색
/* 해당 문제 설명은 링크로 대체한다. */
📌풀이
프로세스
- info 배열에 각 행(문자열)에서 조건별로 문자열을 트리밍하여 점수로 보관
- 점수를 기준으로 오름차순 정렬
- query 배열에 각 행(쿼리열)에서 조건을 나타내는 문자열을 얻어와 이진탐색을 통해 점수와 같은 값 중 가장 첫 번째 위치 값을 가져온다.
0. 필요 변수 초기화
vector<int> answer(query.size(), 0);
: query와 동일한 사이즈인 vector, 0으로 초기화(안해두면 값 이상함)map<string, vector<int>> m;
: first는 조건, second는 조건에 해당하는 점수배열 맵
//동일 조건에 여러 사람의 점수가 존재할 수 있으므로 점수 부분은 vector
1. info 배열에 각 행(문자열)에서 조건별로 문자열을 트리밍하여 점수로 보관
vector<vector<string>> str(4, vector<string>(2, "-"));
: -로 초기 문자열을 세팅한다.
ex. "javabackendjuniorpizza"가 파싱 결과라면, "-backendjuniorpizza", "--juniorpizza", "---pizza"...
이런 식으로 쿼리에서 나올 수 있는 조건을 모두 map에 담아줄 수 있도록 함
for(int i = 0; i < info.size(); i++){
string token = "";
stringstream ss(info[i]);
vector<vector<string>> str(4, vector<string>(2, "-")); //4x2짜리 문자열 배열 --언어, 직군, 경력, 소울푸드를 담는 배열
int index = 0, score = 0;
//한 개씩 공백을 기준으로 조건을 str에 담음. 점수는 score에
while(ss >> token){
if(index < 4) //조건
str[index++][0] = token;
else //점수
score = stoi(token);
}
//점수는 점수대로 보관, 각 조건은 합쳐서 하나의 문자열로
for (int i = 0; i < 2; i++){
string t1, t2, t3, t4;
t1 = str[0][i]; //언어
for (int j = 0; j < 2; j++){
t2 = str[1][j]; //직군
for (int k = 0; k < 2; k++){
t3 = str[2][k]; //경력
for (int l = 0; l < 2; l++){
t4 = str[3][l]; //소울푸드
m[t1 + t2 + t3 + t4].push_back(score);
}
}
}
}
}
- 점수를 기준으로 오름차순 정렬
for(auto itr = m.begin(); itr != m.end(); itr++)
sort(itr->second.begin(), itr->second.end());
- for(auto a : m) 으로 하면 안된다 ...
- 쿼리를 비교할 때 lower_bound()를 이용하여 이진탐색을 진행하려면 반드시 오름차순 정렬 필수
- query 배열에 각 행(쿼리열)에서 조건을 나타내는 문자열을 얻어와 이진탐색을 통해 점수와 같은 값 중 가장 첫 번째 위치 값을 가져온다.
for(int i = 0; i < query.size(); i++){ string str = "", token; stringstream ss(query[i]); int index = 0, score = 0; while(ss >> token){ if(token == "and") continue; //and가 나오면 다음 조건으로 if(index++ < 4) //조건이 4개니까 str += token; else //4이상이라면 마지막 점수 값이 해당되겠지 ? score = stoi(token); } auto itr = lower_bound(m[str].begin(), m[str].end(), score); //이진탐색으로 score와 같거나 큰 반복자 구함 answer[i] = m[str].size() - (itr - m[str].begin()); //실제 인덱스 위치 찾기 위해 m[str].begin() 빼줌 }
📌코드
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <algorithm>
using namespace std;
vector<int> solution(vector<string> info, vector<string> query) {
vector<int> answer(query.size(), 0); //query와 동일한 사이즈인 vector, 0으로 초기화 //안해두면 값 이상함
map<string, vector<int>> m; //first : 조건, second : 조건에 해당하는 점수배열 -- 동일 조건에 여러 사람의 점수가 존재할 수 있으므로
for(int i = 0; i < info.size(); i++){
string token = "";
stringstream ss(info[i]);
vector<vector<string>> str(4, vector<string>(2, "-")); //4x2짜리 문자열 배열 --언어, 직군, 걍략, 소울푸드를 담는 배열
int index = 0, score = 0;
//한 개씩 공백을 기준으로 조건을 str에 담음. 점수는 score에
while(ss >> token){
if(index < 4)
str[index++][0] = token;
else
score = stoi(token);
}
//점수는 점수대로 보관, 각 조건은 합쳐서 하나의 문자열로
for (int i = 0; i < 2; i++)
{
string t1, t2, t3, t4;
t1 = str[0][i];
for (int j = 0; j < 2; j++)
{
t2 = str[1][j];
for (int k = 0; k < 2; k++)
{
t3 = str[2][k];
for (int l = 0; l < 2; l++)
{
t4 = str[3][l];
m[t1 + t2 + t3 + t4].push_back(score);
}
}
}
}
}
//점수를 기준으로 오름차순 진행 (lower_bound)을 위해
for(auto itr = m.begin(); itr != m.end(); itr++)
sort(itr->second.begin(), itr->second.end());
//쿼리를 기준으로 분할하여 비교
for(int i = 0; i < query.size(); i++){
string str = "", token;
stringstream ss(query[i]);
int index = 0, score = 0;
while(ss >> token){
if(token == "and") continue; //and가 나오면 다음 조건으로
if(index++ < 4)
str += token;
else
score = stoi(token);
}
auto itr = lower_bound(m[str].begin(), m[str].end(), score); //이진탐색으로 score와 같거나 큰 반복자 구함
answer[i] = m[str].size() - (itr - m[str].begin()); //실제 인덱스 위치 찾기 위해 m[str].begin() 빼줌
}
return answer;
}
회고
아직도 한참 멀었다. 진심.
개인적으로 아주 많이 어려웠던 문제였다.
문제 내 조건이 많았고, info에서 조건 별로 끄집어내어 효율적으로 저장하려고 구조체도 만들어보고 배열도 만들어보고 북치고 장구치고 하다가 결국 구글링하여 문제를 풀었다. 개개개개개개ㅐ객어렵고 꼭 더 풀어봐야겠다.
추가로 lower_bound()함수를 통해 이진 탐색을 하는 것을 알게되었다. 대박대박 노션에 정리해두어야지 ....
확실히 머리로 이해하고 넘기는 것보다 구글링을 했더라도 노션에 사용했던 STL 함수나 개념 중 헷갈리거나 완벽히 이해하지 못한 것을 적어두고, 블로그에도 해당 문제에 대해서 정리하면서 복기를 하니 조금은 다음 문제 풀이에 도움이 되는 것 같다.
다 ... 나의 거름이 되..겠지...이...?
'코딩테스트 공부 > Programmers' 카테고리의 다른 글
[C++] level2 후보키 42890 (0) | 2021.08.22 |
---|---|
[C++] 위클리챌린지 2주차 83201 (0) | 2021.08.22 |
[C++] level2 수식최대화 67257 (0) | 2021.08.21 |
[C++] level2 [3차] n진수 게임 17687 (0) | 2021.08.21 |
[C++] level2 뉴스 클러스터링 17677 (0) | 2021.08.21 |
댓글