📝 문제
선행 스킬이란 어떤 스킬을 배우기 전에 먼저 배워야 하는 스킬을 뜻합니다.
예를 들어 선행 스킬 순서가 스파크 → 라이트닝 볼트 → 썬더일때, 썬더를 배우려면 먼저 라이트닝 볼트를 배워야 하고, 라이트닝 볼트를 배우려면 먼저 스파크를 배워야 합니다.
위 순서에 없는 다른 스킬(힐링 등)은 순서에 상관없이 배울 수 있습니다. 따라서 스파크 → 힐링 → 라이트닝 볼트 → 썬더와 같은 스킬트리는 가능하지만, 썬더 → 스파크나 라이트닝 볼트 → 스파크 → 힐링 → 썬더와 같은 스킬트리는 불가능합니다.
선행 스킬 순서 skill과 유저들이 만든 스킬트리1를 담은 배열 skill_trees가 매개변수로 주어질 때, 가능한 스킬트리 개수를 return 하는 solution 함수를 작성해주세요.
제한 조건
- 스킬은 알파벳 대문자로 표기하며, 모든 문자열은 알파벳 대문자로만 이루어져 있습니다.
- 스킬 순서와 스킬트리는 문자열로 표기합니다.
- 예를 들어, C → B → D 라면 "CBD"로 표기합니다
- 선행 스킬 순서 skill의 길이는 1 이상 26 이하이며, 스킬은 중복해 주어지지 않습니다.
- skill_trees는 길이 1 이상 20 이하인 배열입니다.
- skill_trees의 원소는 스킬을 나타내는 문자열입니다.
- skill_trees의 원소는 길이가 2 이상 26 이하인 문자열이며, 스킬이 중복해 주어지지 않습니다.
🔑 풀이
1. 스택을 이용한 풀이
function solution(skill, skill_trees) {
let answer = 0;
skill_trees.forEach(v => {
if(check(v)) answer ++;
})
return answer;
function check(str) {
let stack = [];
for(let i = 0; i < skill.length; i++) {
let index = str.indexOf(skill[i]);
if(index >= 0) {
if(stack[stack.length-1] === -1) return false;
if(stack[stack.length-1] > index) return false;
stack.push(index);
}
else stack.push(-1);
}
return true;
}
}
직접 풀어 통과한 풀이로, 스택을 사용하여 풀었다.
스킬 트리 문자열을 순회하여 선행이 필요한 스킬이 있는지 찾고, 있다면 해당 인덱스를 저장했다.
그 과정에서 다음 선행스킬이 존재하지 않으면 0을 집어넣어 더 이상 스택이 채워지지 않도록 한다.
- 정확도 테스트 결과
2. 정규식을 이용한 풀이
function solution(skill, skill_trees) {
let answer = 0;
// 1. skill의 문자를 제외한 문자열을 찾는 정규식
let regex = new RegExp(`[^${skill}]`, 'g');
return skill_trees.map(v => v.replace(regex, ''))
// 2. 스킬트리 각 요소에서 skill이 아닌 것 제거
.filter(v => skill.indexOf(v) === 0 || v === "").length;
// 3. skill이 C부터 순서대로 들어가있는 것만 남김, 갯수 세서 return
}
정규식 [^문자]
: 문자 이외의 문자열 찾음
- skill의 문자를 제외한 문자열을 찾는 정규식
- 모든 스킬 트리에서 선행 트리 이외의 것을 모두 제거한다
indexOf
로 선행스킬이 차례대로 포함되어 있나 확인indexOf
는 인자를 모두 포함해야하며, 발견한 첫번째 인덱스를 반환한다.
C부터 순서대로 나와야 하므로 반환값이 0이거나, 값이 아예 선행스킬과 동일해서''
가 된 요소만 걸러준다.
'CDB'.indexOf('CD')
= 0'CDB'.indexOf('DB')
= 1'CDB'.indexOf('CB')
= -1 (발견 못함)
- 정확도 테스트 결과
다른 풀이
function solution(skill, skill_trees) {
function check(str) {
let skillArr = skill.split('');
for(let i = 0; i < str.length; i++) {
if(!skillArr.includes(str[i])) continue;
if(str[i] === skillArr.shift()) continue;
else return false;
}
return true;
}
return skill_trees.filter(check).length;
}
기발하고 간단한 풀이!
skill을 배열로 바꾼 뒤, 스킬트리에 선행 스킬이 있는지 확인 후, skill 배열에서 하나씩 꺼내 맞춰본다.
- 정확도 테스트 결과
참고
'Coding test' 카테고리의 다른 글
[프로그래머스] 쿼드압축 후 개수세기 (Lv 2) - javascript (0) | 2022.06.16 |
---|---|
[프로그래머스] 이진 변환 반복하기 (Lv 2) - javascript (0) | 2022.06.16 |
[프로그래머스] 2xn 타일링 (Lv 2) - javascript (0) | 2022.06.14 |
[프로그래머스] 3xn 타일링 (Lv 2) - javascript (0) | 2022.06.14 |
[프로그래머스] 숫자 블록 (Lv 2) - javascript (0) | 2022.06.12 |