[프로그래머스] (JavaScript) 단어 변환 - BFS
문제 설명
두 개의 단어 begin, target 과 단어의 집합 words 가 있다. 아래의 규칙을 이용하여 begin 에서 target 으로 변환하는 가장 짧은 변환 과정을 찾으려 한다.
- 한 번에 한 개의 알파벳만 바꿀 수 있다.
- 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 함수를 작성하자.
제한 사항
- 각 단어는 알파벳 소문자로만 이뤄짐
- 각 단어의 길이는 3 이상 10 이하, 모든 단어의 길이는 같음
- words 에는 3개 이상 50개 이하의 단어가 있으며, 중복 X
- begin 과 target 은 같지 않음
- 변환할 수 없는 경우 0 을 return
입출력 예
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 안에 없기 때문에 변환할 수 없음
정답 코드
function solution(begin, target, words) {
let answer = 0;
const visited = new Array(words.length).fill(false);
const queue = [[begin, answer]];
while (queue.length) {
let [word, answer] = queue.shift();
if (word == target) return answer;
for (let i = 0; i < words.length; i++) {
let diffCnt = 0;
if (visited[i]) continue;
for (let j = 0; j < word.length; j++) {
if (word[j] == words[i][j]) {
continue;
} else {
diffCnt++;
}
if (diffCnt > 1) break;
}
if (diffCnt == 1) {
visited[i] = true;
queue.push([words[i], answer + 1])
}
}
}
return answer;
}
코드 풀이
const visited = new Array(words.length).fill(false);
const queue = [[begin, answer]];
각 words 의 방문 여부를 담는 배열 visited 와, 단어를 변환할 때의 단어와 변환 횟수를 담는 queue 를 생성해 준다.
while (queue.length) {
let [word, answer] = queue.shift();
if (word == target) return answer;
// for (let i = 0; i < words.length; i++) {
// let diffCnt = 0;
// if (visited[i]) continue;
// for (let j = 0; j < word.length; j++) {
// if (word[j] == words[i][j]) {
// continue;
// } else {
// diffCnt++;
// }
// if (diffCnt > 1) break;
// }
// if (diffCnt == 1) {
// visited[i] = true;
// queue.push([words[i], answer + 1])
// }
// }
// }
// return answer;
}
queue 의 길이가 0이 아닐때까지 while 문이 반복하는데, 반복할 때마다 queue 의 맨 앞에 있는 수를 shift( ) 하여 현재 단어인 word 와 현재 변환 횟수인 answer 을 변수에 담아준다.
그리고 그 word 와 target 이 같으면 변환 횟수인 answer 을 return 해준다.
for (let i = 0; i < words.length; i++) {
let diffCnt = 0;
if (visited[i]) continue;
// for (let j = 0; j < word.length; j++) {
// if (word[j] == words[i][j]) {
// continue;
// } else {
// diffCnt++;
// }
// if (diffCnt > 1) break;
// }
// if (diffCnt == 1) {
// visited[i] = true;
// queue.push([words[i], answer + 1])
// }
}
그리고 해당 word 를 words[i] 단어를 전부 비교한다.
한 알파벳만 달라야 하니, 다른 횟수를 담는 diffCnt 변수를 생성하고, words[i] 단어로 이미 바뀌었던 단어이면 비교하는 for 문을 돌지 않고 다음 words[i] 과 비교하기 위해 continue 한다.
for (let j = 0; j < word.length; j++) {
if (word[j] == words[i][j]) {
continue;
} else {
diffCnt++;
}
if (diffCnt > 1) break;
}
// if (diffCnt == 1) {
// visited[i] = true;
// queue.push([words[i], answer + 1])
// }
방문 여부가 false 인 words[i] 와 현재 단어 word 가 j 번째의 알파벳이 서로 같으면 j + 1 번째 알파벳을 비교하기 위해 continue 하고, 다르면 diffCnt 를 올린다.
그렇게 알파벳 하나씩 비교하다가 다른 횟수인 diffCnt 가 1 보다 크면 2개 이상 알파벳이 다른 단어이므로 다음 words[i] 와 비교하기 위해 해당 for 문을 종료한다.
if (diffCnt == 1) {
visited[i] = true;
queue.push([words[i], answer + 1])
}
위의 for 문을 정상적으로 다 돌고 난 뒤 diffCnt 가 1인 words[i] 를 찾아 해당 words[i] 를 방문 처리한 후, 해당 word 를 words[i] 로 바꾸고 answer + 1 을 한 뒤 queue 에 넣어준다.
풀이 상세
하나씩 순차적으로 실행하여 가장 빨리 찾아진 것이 최단 방법이므로 순열을 이용한 BFS 방식으로 풀었다.
입출력 예시로 설명해 보겠다.
begin : "hit"
target : "cog"
words : ["hot", "dot", "dog", "lot", "log", "cog"]
queue ["hit", 0], (f, f, f, f, f, f)
queue.shift( ) → queue [ ]
"hit", 0
i = 0 → "hit" hot && f [조건 O] → queue ["hot", 1], (t, f, f, f, f, f)
i = 1 → "hit" dot [조건 X]
i = 2 → "hit" dog [조건 X]
i = 3 → "hit" lot [조건 X]
i = 4 → "hit" log [조건 X]
i = 5 → "hit" cog [조건 X]
queue ["hot", 1], (t, f, f, f, f, f)
queue.shift( ) → queue [ ]
"hot", 1
i = 0 → t [조건 X]
i = 1 → "hot" dot && f [조건 O] → queue ["dot", 2], (t, t, f, f, f, f)
i = 2 → "hot" dog [조건 X]
i = 3 → "hot" lot && f [조건 O] → queue ["dot", 2] ["lot", 2], (t, t, f, t, f, f)
i = 4 → "hot" log [조건 X]
i = 5 → "hot" cog [조건 X]
queue ["dot", 2] ["lot", 2], (t, t, f, t, f, f)
queue.shift( ) → queue ["lot", 2]
"dot", 2
i = 0 → t [조건 X]
i = 1 → t [조건 X]
i = 2 → "dot" dog && f [조건 O] → queue ["lot", 2] ["dog", 3], (t, t, t, t, f, f)
i = 3 → t [조건 X]
i = 4 → "dot" log [조건 X]
i = 5 → "dot" cog [조건 X]
queue ["lot", 2] ["dog", 3], (t, t, t, t, f, f)
queue.shift( ) → queue ["dog", 3]
"lot", 2
i = 0 → t [조건 X]
i = 1 → t [조건 X]
i = 2 → t [조건 X]
i = 3 → t [조건 X]
i = 4 → "lot" log && f [조건 O] → queue ["dog", 3] ["log", 3], (t, t, t, t, t, f)
i = 5 → "lot" cog [조건 X]
queue ["dog", 3] ["log", 3], (t, t, t, t, t, f)
queue.shift( ) → queue ["log", 3]
"dog", 3
i = 0 → t [조건 X]
i = 1 → t [조건 X]
i = 2 → t [조건 X]
i = 3 → t [조건 X]
i = 4 → t [조건 X]
i = 5 → "dog" cog && f [조건 O] → queue ["log", 3] ["cog", 4], (t, t, t, t, t, t)
queue ["log", 3] ["cog", 4], (t, t, t, t, t, t)
queue.shift( ) → queue ["cog", 4]
"log", 3
i = 0 → t [조건 X]
i = 1 → t [조건 X]
i = 2 → t [조건 X]
i = 3 → t [조건 X]
i = 4 → t [조건 X]
i = 5 → t [조건 X]
queue ["cog", 4], (t, t, t, t, t, t)
queue.shift( ) → queue [ ]
"cog", 4
"cog" == target > answer 4
'💠문제 풀이 > 코딩 테스트 문제 풀이' 카테고리의 다른 글
[프로그래머스] (Java) 배달 - 다익스트라 알고리즘 (0) | 2025.01.13 |
---|---|
[프로그래머스] (JavaScript) 네트워크 - DFS (0) | 2024.06.05 |
[프로그래머스] (JavaScript) 타겟 넘버 - DFS (1) | 2024.06.03 |
[프로그래머스] (JavaScript) 피로도 - DFS (1) | 2024.06.01 |