곰퓨타의 SW 이야기

[프로그래머스 level2 스킬트리] 📌큐를 활용해보자 본문

TIL/프로그래머스

[프로그래머스 level2 스킬트리] 📌큐를 활용해보자

곰퓨타 2020. 12. 27. 15:31

level2를 시작하고나니 확실히 난이도가 올라갔다는 것을 느낄 수 있었다 😂

 

해결해야하는 문제는 다음과 같았다

programmers.co.kr/learn/courses/30/lessons/49993

 

코딩테스트 연습 - 스킬트리

 

programmers.co.kr

 

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

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

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

선행 스킬 순서 skill과 유저들이 만든 스킬트리1를 담은 배열 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

 

 

문제를 읽으며 각 skill_trees를 확인해야 하고,

skill 길이에 맞는 배열 temp를 만들어서 뒤에 skill부터 skill tree에 있는지 확인해야 겠다고 생각하였다.

 

뒤쪽 skill이 존재하기 위해서는 반드시 앞의 스킬이 필요로 하므로,

해당 skill이 존재한다면 현재 skill_trees에서 해당 skill 전까지를 검사하는 방식으로 접근하였다.

 

skill이 있다는 것은 temp 배열에 1을 해주어 체크할 수 있도록 하였다.

끝까지 skill 순서를 지키며 skill_trees가 작성된 경우에는 answer값을 1 더해주었다.

 

내 아이디어로 작성된 코드는 다음과 같다.

def solution(skill, skill_trees):
    answer = 0
    for i in skill_trees :
        temp = [0]*len(skill)
        j=len(skill)-1
        tmpTree = i
        while True:
            if j==len(skill)-1 and skill[j] in tmpTree :
                tmpTree = tmpTree[:tmpTree.index(skill[j])]
                temp[j] = 1
                j -= 1
            elif j != len(skill)-1 and 1 in temp[j+1:]:
                if skill[j] in tmpTree:
                    tmpTree = tmpTree[:tmpTree.index(skill[j])]
                    temp[j] = 1
                    j -= 1
                else :
                    break
            else :
                if skill[j] in tmpTree:
                    tmpTree = tmpTree[:tmpTree.index(skill[j])]
                    temp[j] = 1
                    j -= 1
                else :
                    j-=1
            if j==-1:
                answer+=1
                break

    return answer

 

코드를 완료하면 다른 사람의 풀이를 확인할 수 있으므로, 더 간단한 방법이 무엇인지 궁금하여 다른 사람의 풀이를 보았다.

def solution(skill, skill_trees):
    answer = 0

    for skills in skill_trees:
        skill_list = list(skill)

        for s in skills:
            if s in skill:
                if s != skill_list.pop(0):
                    break
        else:
            answer += 1

    return answer

 

 

이는 skills 에 있는 문자열을 리스트로 변환해준 후,

변환된 리스트를 순환하며 skill에 있는데, skill의 첫번째 요소가 아니면 선행학습의 순서를 어긴 것이므로 해당 트리는 불가능하다고 판단하여 break 하였다.

 

처음 알게 된 것인 for~else는 for문이 문제 없이 다 돌아간 경우 else문을 실행한다는 것이다. (파이썬의 세계는 역시 신기하다...🙆‍♀️)

따라서 for문에 성공적으로 실행된 경우 가능한 스킬트리이므로 answer += 1을 해준 것이다.

 

이 코드를 보며 유연한 사고를 기르는 연습은 꾸준히 해야겠다는 것을 느꼈다⭐️

Comments