View

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 합니다.

 

문제 해결 아이디어

일단 문제를 해결하기 전에 words에 target이 없다면 어차피 변환할 수 없기에 return 0을 반환하고 시작한다.

 

한 번에 한 개의 알파벳만 바꿀 수 있으므로 words의 각 원소마다 한 개의 알파벳만 바꾸었을 때 words의 원소들이 될 수 있는지 표시해 준다. 예를 들면 word가 hot일 때 lot으로는 바꿀 수 있지만 dog로는 못 바꾸니까 words[hot][lot]은 1이고 words[hot][dog]는 0이다. isPossible 함수로 검사해 줘서 bfs 돌 인접행렬을 만들어 준다!

 

이제 1과 0으로 표시된 인접행렬을 bfs 돌린다. begin에서 target으로 가는 방법은 여러 개가 있을 수 있기 때문에 bfs 돌고 난 후에 결과 최솟값을 저장한다. 

돌리는 조건에 대해 살펴보면, 되돌아오는 걸 방지하기 위해 visited 배열을 사용해서 그 값이 false인 경우와 begin으로 시작해 한 번 바꿔질 수 있는 단어들에 대해 bfs를 돌게 된다.

bfs는 앞서 설명했듯이 방문하지 않고 인접행렬의 값이 1인 경우에 대해 계속해서 탐색하게 된다.

그리고 target에 도달했을 때의 깊이를 저장하게 된다.

 

완성된 코드

import java.util.*;

class Solution {
    static int[][] possible;
    static boolean[] visited;
    public int solution(String begin, String target, String[] words) {
        int answer = Integer.MAX_VALUE;
        
        possible = new int[words.length][words.length];
                              
        boolean flag = false;
        for (int i = 0; i < words.length; i++) {
            if (target.equals(words[i]))
                flag = true;
       }
        if (!flag) return 0;
        
        for (int i = 0; i < words.length; i++) {
            String now = words[i];
            for (int j = 0; j < words.length; j++) {
                if (i == j) 
                    continue;
                if (isPossible(now, words[j]))
                    possible[i][j] = 1;
            }
        }
        
        int result = Integer.MAX_VALUE;
                              
        for (int i = 0; i < words.length; i++) {
            visited = new boolean[words.length];
            if (!visited[i] && isPossible(begin, words[i])) {
                visited[i] = true;
                result = bfs(begin, target, words, i);
                if (result == 0) continue;
                answer = Math.min(result, answer);
            }
        }
        
        return answer;
    }
    
    public int bfs(String begin, String target, String[] words, int now) {
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[] {now, 1});
        
        int result = 0;
        while (queue.size() > 0) {
            int[] current = queue.poll();
            if (words[current[0]].equals(target)) {
                result = current[1];
                break;
            }

            for (int i = 0; i< words.length; i++) {
                if (possible[current[0]][i] == 1 && !visited[i]) {
                    visited[i] = true;
                    queue.offer(new int[] {i, current[1] + 1});
                }
            }
        }
        return result;
    }
    public boolean isPossible(String now, String target) {
        char[] nowArr = now.toCharArray();
        char[] targetArr = target.toCharArray();
    
        int length = nowArr.length;
        int cnt = nowArr.length;
        for (int i =0; i < length; i++) {
            if (nowArr[i] != targetArr[i])
                cnt--;
        }
        
        if (length-1 == cnt) return true;
        else return false;
        
    }
}

 

Share Link
reply
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30