본문 바로가기

프로그래머스 문제풀이/레벨 2

[레벨2] 스킬트리

[문제설명] 스킬트리

선행 스킬이란 어떤 스킬을 배우기 전에 먼저 배워야 하는 스킬을 뜻합니다.

예를 들어 선행 스킬 순서가 스파크 → 라이트닝 볼트 → 썬더일때, 썬더를 배우려면 먼저 라이트닝 볼트를 배워야 하고, 라이트닝 볼트를 배우려면 먼저 스파크를 배워야 합니다.

위 순서에 없는 다른 스킬(힐링 등)은 순서에 상관없이 배울 수 있습니다. 따라서 스파크 → 힐링 → 라이트닝 볼트 → 썬더와 같은 스킬트리는 가능하지만, 썬더 → 스파크 라이트닝 볼트 → 스파크 → 힐링 → 썬더와 같은 스킬트리는 불가능합니다.

선행 스킬 순서 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