두 개의 단어 begin
, target
과 단어의 집합 words
가 있습니다. 아래와 같은 규칙을 이용하여 begin에서 target으로 변환하는 가장 짧은 변환 과정을 찾으려고 합니다.
1. 한 번에 한 개의 알파벳만 바꿀 수 있습니다.
2. words에 있는 단어로만 변환할 수 있습니다.
예를 들어 begin이 "hit", target가 "cog", words가 ["hot","dot","dog","lot","log","cog"]라면 "hit" -> "hot" -> "dot" -> "dog" -> "cog"와 같이 4단계를 거쳐 변환할 수 있습니다.
두 개의 단어 begin, target과 단어의 집합 words가 매개변수로 주어질 때, 최소 몇 단계의 과정을 거쳐 begin을 target으로 변환할 수 있는지 return 하도록 solution 함수를 작성해주세요.
제한사항
입출력 예
begin | target | words | return |
---|---|---|---|
"hit" | "cog" | ["hot", "dot", "dog", "lot", "log", "cog"] | 4 |
"hit" | "cog" | ["hot", "dot", "dog", "lot", "log"] | 0 |
입출력 예 설명
예제 #1
문제에 나온 예와 같습니다.
예제 #2
target인 "cog"는 words 안에 없기 때문에 변환할 수 없습니다.
begin
에서 target
이 되는 과정을 트리로 생각했다.
만약 begin: hit
, target: cog
, words: hot, hig, hiz, dot, lot, log
이라면
한 단계마다 한 단어씩 바꾼다고 할 때 아래처럼 트리로 나타낼 수 있다.
최소 단계를 구해야 하니까, 위 트리처럼 봤을 때 트리의 레벨이 정답이 된다.
begin
에서 시작해 한 문자만 바꿔 만들 수 있는 단어들을 구하고, target
이 된다면 몇 단계를 거쳤는지 반환하게 했다.
여기서 이미 사용한 word는 다음 단계에서 못 사용하게 해야 한다.
소스코드
// 두 단어가 알파벳 하나 차이로 다르다면 true 반환
function isSimilarStr(str1, str2) {
let cnt = 0;
for (let i=0; i<str1.length; i++) {
if (str1[i] !== str2[i]) cnt++;
if (cnt > 1) return false;
}
if (cnt === 0) return -1;
return true;
}
function solution(begin, target, words) {
// words에 target이 없으면 0 반환
if (!words.includes(target)) return 0;
// visited: 방문한 단어, base: 비교할 기준이 되는 단어, step: 단계
let visited = [], base = [begin], step = 0;
while (visited.length < words.length) {
// next: 해당 단계에서 base와 유사한 단어들을 모아놓은 배열
let next = [];
// base 단어를 기준으로 words 단어들 비교
for (let i=0; i<base.length; i++) {
for (let j=0; j<words.length; j++) {
// words 문자가 방문한 문자가 아니며 base와 유사하다면
if (!visited.includes(words[j]) && isSimilarStr(base[i], words[j])) {
next.push(words[j]);
visited.push(words[j]);
}
}
}
// 유사한 단어가 없다면, 이어질 수 없으므로 끝남
if (next.length < 1) return 0;
// 유사한 단어들 중에 target이 있다면 step 반환
step++;
if (next.includes(target)) return step;
// 기준을 next 값으로 갱신
base = next;
}
return 0;
}