프로그래머스 직업군 추천하기 (C++)
문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/84325#
문제 요약
(문제 링크에는 각 벡터의 도표와 함께 설명이 디테일하게 나와있으므로, 문제 링크를 통해 자세히 보는 것을 추천합니다.)
1. vector<string>에는 직군별 선호 언어가 나열되어있다. 맨 첫번째 단어는 직군의 명칭이며, 공백을 기준으로 선호 언어가 나열된다. 선호 언어는 5점에서 1점순으로 나열된다.
2. vector<string> languages와 vector<int> preference가 주어진다. 두 벡터의 크기는 동일하며, languages[i]번째 언어의 선호점수는 preference[i]번째 숫자이다.
3. 각 직군별 개발 언어 점수를 구하여라. 점수가 동일할 경우 사전순으로 먼저 오는 직군을 출력하라.
핵심 포인트
이 문제는 크게 아래와 같은 로직으로 접근하여 풀었습니다.
- languages의 점수들을 unordered_map에 저장하여 key : value로 접근이 가능하도록 설정
- 각 직군별로 언어 점수들을 구하여 unordered_map에 저장. 마찬가지로 key : value로 접근이 가능하도록 설정
- 선호 점수가 가장 높은 것을 정답으로 출력하며, 동일한 점수는 문자열의 크기가 더 작은 값을 출력
추가로 문자열 관련 함수를 잘 알고있다면 쉽게 풀 수 있습니다.
문제 풀이
먼저 전체 로직을 훑어보겠습니다.
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
unordered_map<string,int> score;
unordered_map<string,int> answer;
void scoreSetting(vector<string> &languages, vector<int> &preference){
for(int i=0; i<languages.size(); i++) score[languages[i]] = preference[i];
return;
}
void userScoreSetting(vector<string> &table){
for(int i=0; i<table.size(); i++){
int cnt = 6, st = 0, ed = 0;
string job = "", temp = "";
while(ed!=table[i].npos){
ed = table[i].find(' ',st);
if(ed!=table[i].npos) temp = table[i].substr(st,ed-st);
else temp = table[i].substr(st);
if(cnt==6) {
job = temp;
answer[job] = 0;
}
if(score.find(temp)!=score.end()) answer[job] += cnt*score[temp];
st = ed+1;
cnt--;
}
}
}
string solution(vector<string> table, vector<string> languages, vector<int> preference) {
string ans1 = "";
int ans2 = 0;
scoreSetting(languages, preference); // 1. languages 점수 구분하기
userScoreSetting(table); // 2. 직군별 점수 구하기
for(auto a : answer){ // 3. 가장 높은 점수의 직군 구하기
if(ans2<a.second){
ans1 = a.first;
ans2 = a.second;
}
else if(ans2==a.second){
if(ans1>a.first){
ans1 = a.first;
ans2 = a.second;
}
}
}
return ans1;
}
(1) 첫 번째로 languages의 언어를 구분하여 언어별 점수를 저장합니다.
void scoreSetting(vector<string> &languages, vector<int> &preference){
for(int i=0; i<languages.size(); i++) score[languages[i]] = preference[i];
return;
}
(2) 다음으로 직군별 언어 점수를 구합니다.
void userScoreSetting(vector<string> &table){
for(int i=0; i<table.size(); i++){ // 1
int cnt = 6, st = 0, ed = 0; // 2
string job = "", temp = "";
while(ed!=table[i].npos){ // 3
ed = table[i].find(' ',st); // 4
if(ed!=table[i].npos) temp = table[i].substr(st,ed-st); // 5
else temp = table[i].substr(st); // 6
if(cnt==6) { // 7
job = temp;
answer[job] = 0;
}
if(score.find(temp)!=score.end()) answer[job] += cnt*score[temp]; // 8
st = ed+1; // 9
cnt--; // 10
}
}
}
(1) table의 사이즈만큼 for문을 돌립니다.
(2) cnt는 언어별 점수, st와 ed는 문자열을 자르는 구간을 뜻하는 변수입니다.
(3) ed가 table[i]안에 존재할때까지 while문을 돌립니다.
(4) st번째 이상부터 시작하여 첫 번째로 만나는 ' '(공백)의 위치를 ed에 저장합니다.
(5) 만약 ed가 table[i]안에 위치할 경우, temp 문자열은 table[i]의 st부터 시작하여 ed-st개의 갯수만큼 저장합니다.
참고로 substr(a,b)는 a부터 시작하여 b개만큼 저장한다는 것을 유의해야합니다.
(6) ed가 table[i]안에 위치하지 않을 경우, table[i]의 마지막 단어라는 뜻입니다. table[i].suhstr(st)로 모든 단어를 temp에 저장합니다.
(7) 만약 cnt가 6일 경우, job에 해당되는 단어를 구했다는 뜻입니다. answer[job] = 0으로 초기화해줍니다.
(8) score에 temp가 존재할경우, cnt*temp의 점수만큼 answer[job]에 더해줍니다.
(9) 다음턴에 다시 새로운 ' '(공백)을 찾기 위해 st = ed +1로 저장합니다.
(10) cnt는 -1해줍니다.
(3) 다음은 정답을 찾는 구간입니다.
string solution(vector<string> table, vector<string> languages, vector<int> preference) {
string ans1 = "";
int ans2 = 0;
scoreSetting(languages, preference);
userScoreSetting(table);
for(auto a : answer){ // 1
if(ans2<a.second){ // 2
ans1 = a.first;
ans2 = a.second;
}
else if(ans2==a.second){ // 3
if(ans1>a.first){ // 4
ans1 = a.first;
ans2 = a.second;
}
}
}
return ans1; // 5
}
(1) answer의 사이즈만큼 for문을 돌립니다.
(2) a.second의 값이 ans2보다 크다면, ans1에는 해당 직군을, ans2에는 해당 직군의 총합 점수를 저장합니다.
(3) ans2의 값이 a.second와 동일하다면
(4) 동시에 ans1의 값이 a.first보다 크다면, 문자열로 나열했을때 사전순으로 더 앞에 위치하는 직군을 찾았다는 뜻입니다.
ans1에 해당 직군을, ans2에 해당 직군의 총합 점수를 저장합니다.
(5) ans1을 반환하고 종료합니다.