문제: 42. 스킬트리
- 문제 이해
- 선행 스킬: 어떤 스킬을 배우기 전에 먼저 배워야 하는 스킬
- 예시 : 스파크 -> 라이트닝 볼트 -> 썬더
- 순서 없는 다른 스킬들(힐링)등은 순서에 상관없이 배울 수 있다.
- 스파크 -> 힐링 -> 라이트닝 볼트 -> 썬더
-
썬더 스파크와 같은 기존 순서와 맞지 않는 스킬트리는 불가능
- 제한사항
- 스킬은 알파벳 대문자로 표기. 모든 문자열은 알파벳 대문자로 이루어짐
-
스킬의 길이는 2이상 26이하이며, 스킬은 중복해서 주어지지 않음.
- 입출력 예시
- skill: “CBD”,
- skill_trees : [“BACDE”,”CBADF”,AECB”,”BDA”]
-
return 2
- 입출력 예 설명
- “BACDE” : B 스킬을 배우기 전에 C 스킬을 먼저 배워야 한다. 불가능한 스킬트리
- “CBADF” : 가능
- “AECB” : 가능
- “BDA” : B스킬을 배우기 전에 C스킬을 먼저 배워야 한다. 불가능
생각한 방법
- skill의 순서를 기억하기 위해 result 리스트를 만든다.
- skill의 첫번째 문자열과 검사할 문자열을 비교한다. 어떻게 비교 ?
print("C" > "B")
하면 False가 나오고 반대로 하면 True가 나온다.- 파이썬에서는 문자열 비교가 가능하다.
- 아스키 코드로 변환되서 비교가 가능해지며, 문자를 아스키코드로 변환하고 싶다면
ord('a')
와 같은 함수를 사용한다
- 삼중 포문 구현하기가 까다롭다. 1시간 고민하다가 안되서, 결국 찾아봤다.
다른 사람들 풀이
- 스킬트리 중, 스킬에 없는 스킬들은 빼고 임시변수에 저장한다.
- 임시 변수에 길이만큼 스킬을 배우는 순서와 비교한다
- 비교 결과가 같다면 가능한 스킬트리라면 정답 개수를 1 증가시킨다.
- index는 문자열이 어디있는지 반환해준다. 없으면 오류를 발생.
- find의 경우 찾는 문자열이 없으면 -1을 반환해준다.
def solution(skill, skill_trees):
answer = 0
for str in skill_trees:
temp = "" # 스킬에 없는 스킬들은 지우고 저장할 변수
isOk = True # 가능한 스킬트리의 개수를 저장할 변수
# 1. 스킬에 없는 스킬들은 뺴고 temp에 저장
for s in str:
if skill.find(s) != -1:
temp += s
# 2. temp의 길이만큼 스킬과 비교하여
# 같으면 가능한 스킬트리, 다르면 불가능한 스킬트리
for i in range(len(temp)):
if skill[i] != temp[i]:
isOk = False
break
# 3. 가능한 스킬트리라면 정답 개수를 1 증가
if isOk == True:
answer += 1
return answer
다른 사람 풀이 2
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
- 이 방법은 가장 쉽고 직관적이게 풀었다.
- 처음에 이해가 가지 않아서 for-else가 뭔지 찾아보니, 이런 문도 있었다.
for - else 문
- 기본적으로 for문에 break가 포함되어 있을 때 사용 가능하다.
- for문을 순회하는 도중 break문을 만나지 않았다면 for문 종료 이후 else문이 실행된다.
- skill_list에 skill을 복사해준 뒤 ,pop(0)을 해줘서 순서대로 같은 것을 찾아줬다.
- 그 이후 break문이 실행되지 않았다면 answer+=1을 해줘서 정답을 찾아준 것이다.
for a in range(5):
print(a)
if a == 3:
break
else:
print("else statement is called")
- 위 예시코드를 살펴보면
-
실행 결과는 0,1,2,3이다.
- 그런데 break문을 만나지 않는 for문이라면 ?
for a in range(5):
print(a)
if a == 6:
break
else:
print("else statement is called")
이게 출력된다.
- 실행 결과는 0,1,2,3,4와
- else statement is called가 함께 출력된다.
- flag변수를 사용하지 않아도 코드가 훨씬 깔끔해진다.
참고자료 [프로그래머스]https://programmers.co.kr/learn/challenges [참고한 블로그]http://blog.naver.com/PostView.nhn?blogId=h0609zxc&logNo=221479852915&categoryNo=1&parentCategoryNo=1&viewDate=¤tPage=1&postListTopCurrentPage=1&from=postView [find와index차이]https://ssungkang.tistory.com/entry/%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%95%A8%EC%88%98-find%EC%99%80-index [for-else문]http://www.mukgee.com/?p=93