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

☑️ 문제

프로그래머스 43163

☑️ 풀이

첫 번째 풀이 (DFS)

//시간: 0.18ms
//메모리: 87.1MB

import java.util.*;

class Solution {
    public int answer = 100;
    public boolean[] visited;

    public int solution(String begin, String target, String[] words) {
        visited = new boolean[words.length];
        boolean isPossible = false;

        for (String str : words) {
            if (str.equals(target)) {
                isPossible = true;
                break;
            }
        }

        if (!isPossible) {
            return 0;
        }

        dfs(begin, target, words, 0);

        return answer;
    }

    public void dfs(String current, String target, String[] words, int depth) {
        // target과 일치하면 최소 변환 횟수 저장
        if (current.equals(target)) {
            answer = Math.min(depth, answer);
            return;
        }

        for (int i = 0; i < words.length; i++) {
            if (!visited[i] && converted(current, words[i])) {
                visited[i] = true;
                dfs(words[i], target, words, depth + 1);
                visited[i] = false;
            }
        }
    }

    public boolean converted(String current, String word) {
        int cnt = 0;
        for (int i = 0; i < current.length(); i++) {
            if (current.charAt(i) != word.charAt(i)) {
                cnt++;
            }

            if (cnt > 1) {
                return false;
            }
        }
        return cnt == 1;
    }

}
  • DFS에 적용한 개념 정리
    1. DFS는 “재귀(혹은 스택) 기반의 깊이 우선 탐색”을 수행하는 알고리즘
      • 한 경로를 깊게 탐색하다가 더 이상 진행할 수 없으면 이전 단계로 돌아가 다른 경로를 탐색해야 한다.
    2. 모든 가능한 변환 경로를 고려
      • 특정 단어에서 한 글자만 바꿔서 만들 수 있는 모든 후보를 탐색해야 한다.
      • 단순한 배열 순차 탐색이 아니라, 현재 단어에서 한 글자 차이 나는 모든 단어를 찾아 DFS 탐색해야 한다.
    3. 백트래킹(Backtracking) 적용
      • 한 경로로 탐색한 후, 다른 경로도 탐색할 수 있도록 방문 여부를 되돌려야 한다.
    4. 방문 여부를 체크하여 중복 탐색 방지
      • visited 배열을 사용하여 방문한 단어는 다시 방문하지 않도록 관리한다.
  • 최단 변환 과정을 찾아야 하기 때문에 BFS 방식이 더 적절하다.

두 번째 풀이 (BFS)

//시간: 0.64ms
//메모리: 90.7MB

import java.util.*;

class Pair {
    String str;
    int depth;

    public Pair (String str, int depth) {
        this.str = str;
        this.depth = depth;
    }
}

class Solution {
    public int answer = 0;
    public boolean[] visited;

    public int solution(String begin, String target, String[] words) {
        visited = new boolean[words.length];
        boolean isPossible = false;

        for (String str : words) {
            if (str.equals(target)) {
                isPossible = true;
                break;
            }
        }

        if (!isPossible) {
            return 0;
        }

        return bfs(begin, target, words);
    }

    public int bfs(String begin, String target, String[] words) {
        Queue<Pair> queue = new LinkedList<>();
        queue.add(new Pair(begin, 0));

        while (!queue.isEmpty()) {
            Pair pair = queue.poll();
            String current = pair.str;
            int depth = pair.depth;

            if (current.equals(target)) {
                return depth;
            }

            for (int i = 0; i < words.length; i++) {
                if (!visited[i] && converted(current, words[i])) {
                    visited[i] = true;
                    queue.add(new Pair(words[i], depth + 1));
                }
            }
        }

        return 0;
    }

    public boolean converted(String current, String word) {
        int cnt = 0;
        for (int i = 0; i < current.length(); i++) {
            if (current.charAt(i) != word.charAt(i)) {
                cnt++;
            }

            if (cnt > 1) {
                return false;
            }
        }
        return cnt == 1;
    }

}
  • BFS로 다시 풀어보았다.
  • BFS에 적용한 개념 정리
    1. BFS는 큐(Queue) 기반의 너비 우선 탐색을 수행하는 알고리즘
      • 한 단계씩 넓게 탐색하며, 모든 인접한 노드를 먼저 방문한 후 다음 깊이를 탐색한다.
      • 최단 경로 문제에 가장 적합한 탐색
    2. 모든 가능한 변환 경로 고려
      • 현재 단어에서 한 글자만 다른 단어를 찾아 탐색해야 한다.
      • 변환 가능한 모든 단어를 큐에 삽입하여 레벨 단위로 탐색을 진행한다.
      • DFS처럼 한 경로를 끝까지 탐색하는 것이 아니라, 가까운 변환부터 순차적으로 탐색한다.
    3. 최단 경로 보장
      • BFS는 한 단계씩 진행되기 때문에, 가장 먼저 target 에 도달하는 경로가 최단 거리임을 보장한다.
      • depth 를 증가시키며 탐색하고, target 과 일치하면 즉시 탐색을 종료한다.
    4. 방문 여부를 체크하여 중복 탐색 방지
      • visited 배열을 사용하여 이미 탐색한 단어는 다시 방문하지 않는다.

© 2021. All rights reserved.

yaejinkong의 블로그