본문 바로가기
개발/알고리즘

[프로그래머스][LEVEL3] 단어 변환

by ISA(류) 2022. 2. 16.

# 문제 원문

https://programmers.co.kr/learn/courses/30/lessons/43163

 

코딩테스트 연습 - 단어 변환

두 개의 단어 begin, target과 단어의 집합 words가 있습니다. 아래와 같은 규칙을 이용하여 begin에서 target으로 변환하는 가장 짧은 변환 과정을 찾으려고 합니다. 1. 한 번에 한 개의 알파벳만 바꿀 수

programmers.co.kr

두 개의 단어 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 함수를 작성해주세요.

제한사항

  • 각 단어는 알파벳 소문자로만 이루어져 있습니다.
  • 각 단어의 길이는 3 이상 10 이하이며 모든 단어의 길이는 같습니다.
  • words에는 3개 이상 50개 이하의 단어가 있으며 중복되는 단어는 없습니다.
  • 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

 

 

# 문제 풀이

 

탐색문제 입력 받은 begin을 target으로 만드는데 단어를 구성하는 문자 하나만 한번씩 수정 하는 방법으로 words안의 단어들을 이어서 target을 구하는 최소한의 경로를 구하는 문제이다. 최단 경로를 구하는 문제이니 BFS로 풀면 되겠지만 사실 그냥 DFS로 한다해도 나오는 경로중 최소한의 경로를 고르면 된다. target으로 변환을 못하는 경우는 0을 반환하면 되며 words 내부에 target이 없다면 변환하지 못하므로 해당 부분을 얼리리턴해준다. 사실 테스트 케이스 중에 target은 있지만 그거를 이어주는 단어가 없지 않을까? 고민을 조금 해보았으나 현재는 그런 테스트케이스가 없는 것 같다. 사실 그냥 탐색문제로 푼거 같다. dfs 변형으로

 

# 솔루션 플로우

1. 입력 받은 target이 words에 없다면 0을 반환한다.

2. 입력 받은 wrods를 통해서 visited 즉 방문 리스트를 만든다.

3. 입력 받은 begin을 통해서 dfs 또는 bfs 탐색을 시작한다.

4. words를 순회하면서 현재 단어와 차이가 하나인 단어를 찾아서 방문체크하고 탐색을 계속한다. count + 1

5. target과 문자 하나가 다른 경우가 나오면 답이니 result에 count를 push 해준다.

6. 구해진 result 중 가장 작은 수를 구한다. (최단 경로)

7. result를 반환한다.

1. DFS

function solution(begin, target, words) {
    if (!words.includes(target)) return 0;
    const result = [];
    const visited = words.reduce((result, current) => {
        result[current] = false;
        return result;
    }, {});

    const dfs = (current, count) => {
        words.some((word) => {
            let isTarget = 0;
            let isDiff = 0;
            for (let idx = 0; idx < word.length; idx++) {
                if (current[idx] !== target[idx]) isTarget++;
                if (current[idx] !== word[idx]) isDiff++;
            }
            if (isTarget === 1) {
                result.push(count + 1);
                return true;
            } else if (isDiff === 1 && !visited[word]) {
                visited[word] = true;
                dfs(word, count + 1);
            }
        });
    }

    dfs(begin, 0);

    return Math.min(...result);
}

 

 

반응형