[문제설명] 스킬트리
선행 스킬이란 어떤 스킬을 배우기 전에 먼저 배워야 하는 스킬을 뜻합니다.
예를 들어 선행 스킬 순서가 스파크 → 라이트닝 볼트 → 썬더일때, 썬더를 배우려면 먼저 라이트닝 볼트를 배워야 하고, 라이트닝 볼트를 배우려면 먼저 스파크를 배워야 합니다.
위 순서에 없는 다른 스킬(힐링 등)은 순서에 상관없이 배울 수 있습니다. 따라서 스파크 → 힐링 → 라이트닝 볼트 → 썬더와 같은 스킬트리는 가능하지만, 썬더 → 스파크 나 라이트닝 볼트 → 스파크 → 힐링 → 썬더와 같은 스킬트리는 불가능합니다.
선행 스킬 순서 skill과 유저들이 만든 스킬트리를 담은 배열 skill_trees가 매개변수로 주어질 때, 가능한 스킬트리 개수를 return 하는 solution 함수를 작성해주세요.
[제한사항]
- 스킬은 알파벳 대문자로 표기하며, 모든 문자열은 알파벳 대문자로만 이루어져 있습니다.
- 스킬 순서와 스킬트리는 문자열로 표기합니다.
- 예를 들어, C → B → D 라면 CBD로 표기합니다
- 선행 스킬 순서 skill의 길이는 1 이상 26 이하이며, 스킬은 중복해 주어지지 않습니다.
- skill_trees는 길이 1 이상 20 이하인 배열입니다.
- skill_trees의 원소는 스킬을 나타내는 문자열입니다.
- skill_trees의 원소는 길이가 2 이상 26 이하인 문자열이며, 스킬이 중복해 주어지지 않습니다.
[입출력 예시]
skill | skill_trees | return |
"CBD" | ["BACDE", "CBADF", "AECB", "BDA"] | 2 |
[입출력 예시 설명]
- BACDE: B 스킬을 배우기 전에 C 스킬을 먼저 배워야 합니다. 불가능한 스킬트리입니다.
- CBADF: 가능한 스킬트리입니다.
- AECB: 가능한 스킬트리입니다.
- BDA: B 스킬을 배우기 전에 C 스킬을 먼저 배워야 합니다. 불가능한 스킬트리입니다.
[해결방법]
문제를 해결한 방법은 주어진 스킬트리(skill)의 문자열의 문자를 주어진 스킬트리(skill_trees)에 find함수를 통해서 인덱스를 알아낸 다음, 이 인덱스의 크기로 문제를 해결하였다.
for(int i=0;i<skill.size();i++) v.push_back(s.find(skill[i]));
위의 반복문을 통해서 스킬트리의 문자의 인덱스를 확인한 다음 vector에 이를 저장하였다.
for(int i=0;i<v.size();i++){
if(prev<v[i]){
prev = v[i];
continue;
}else{
if(v[i]<0){
for(int j=i+1;j<v.size();j++){
if(v[j]<0) continue;
ans = false;
}
}else{
ans = false;
}
break;
}
}
인덱스를 저장한 다음 이를 비교를 통해서 옳게 배운 스킬트리인지 잘못 배운 것인지를 판단한다.
문제가 그러면 3가지 경우로 나눌수 있게 된다.
1. 이전 단어의 인덱스가 현재 단어의 인덱스보다 작은 경우(이전 인덱스 < 현재 인덱스)
2. 이전 단어의 인덱스가 현재 단어의 인덱스보다 큰 경우(이전 인덱스 >= 현재인덱스)
2-1. 2번과 같은 경우이면서 현재 단어의 인덱스가 음수인 경우이면서 그 뒤의 인덱스가 음수인 경우(뒤에 부분을 배우지 않는 경우)
2-2. 2번과 같은 경우이면서 현재 단어의 인덱스가 음수인 경우이면서 그 뒤의 인덱스는 양수인 경우(스킬트리를 건너 뛴 경우)
해당 하는 경우에 맞게 조건문을 설정해서 해결하면 된다.
- 전체 코드 -
#include <string>
#include <vector>
using namespace std;
int solution(string skill, vector<string> skill_trees) {
int answer = 0;
//스킬트리 안에 있는 문자열을 검사하기 위한 반복문
for(string s: skill_trees){
bool ans = true; //정답임을 확인하기 위한 bool형 변수
int prev=-1;
vector<int> v; // 스킬 문자의 위치를 저장해줄 벡터(스킬을 배우는 순서)
//find 함수를 통해서 현재 정해진 skill의 문자가 주어진
//스킬트리에 어떤 위치에 있는지를 find함수를 통해서 확인한 뒤 저장
for(int i=0;i<skill.size();i++) v.push_back(s.find(skill[i]));
for(int i=0;i<v.size();i++){
if(prev<v[i]){
//이전의 스킬트리가 항상 현재의 것보다 작으면 스킬트리의 순서를 따라가는 것이다.
prev = v[i];
continue;
}else{
if(v[i]<0){
// 현재 위치가 음수일 때, 뒤에 위치도 다 음수이면 배우지 않는 경우이므로 괜찮다.
for(int j=i+1;j<v.size();j++){
if(v[j]<0) continue;
ans = false;
}
}else{
//그냥 문자의 순서가 뒤집어져 있는 경우는 스킬트리의 순서가 뒤집어진 것과 같다.
ans = false;
}
break;
}
}
if (ans) answer++;
}
return answer;
}
출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges
'프로그래머스 문제풀이 > 레벨 2' 카테고리의 다른 글
[레벨2] 멀쩡한 사각형 (0) | 2021.01.18 |
---|---|
[레벨2] 124 나라의 숫자 (0) | 2021.01.18 |
[레벨2] 기능개발 (0) | 2021.01.18 |
[레벨2] 위장 (0) | 2021.01.06 |
[레벨 2] 카카오프렌즈 컬러링북 (0) | 2021.01.06 |