본문 바로가기

알고리즘 고득점 Kit

프로그래머스 단어 변환 Java

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

1. 문제 설명

두 개의 단어 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

입출력 예 설명

예제 #1
문제에 나온 예와 같습니다.

예제 #2
target인 "cog"는 words 안에 없기 때문에 변환할 수 없습니다.

 

2. 시나리오

  • 최소 몇 번의 변환으로 target이 되는지, 최소 거리이기 때문에 BFS를 사용하여 탐색한다.
  • 단어들끼리 한 개의 알파벳만 차이나면 바꿀 수 있는 것이므로 양방향 연결하여 Map에 저장해둔다.
    • 배열의 최대 길이가 50이므로, for문 2번으로 각 단어끼리 모두 연결할 수 있다. O(N^2) 가능
  1. 배열 words의 단어들 중 begin과 한 알파벳만 차이나는 단어들을 Node(단어의 인덱스, 1)로 큐에 모두 넣고, 방문 표시한다. 
    Node단어의 인덱스거리를 멤버 변수로 가진다.
  2. 큐에서 Node를 하나씩 뽑는다.
  3. 뽑은 Node의 단어가 target이면, Node의 거리를 반환한다.
  4. 뽑은 Node의 단어가 target이 아니면, 연결된 단어들 중 방문하지 않은 것들을 Node(단어, 뽑은 Node의 거리 + 1)로 큐에 넣어준다.
  5. 큐가 비지 않을 동안 반복하는데, 만약 변환할 수 없는 경우는 0을 반환하기 때문에 BFS 함수의 마지막에 0을 반환해준다.

 

3. 코드

import java.util.*;

class Solution {
    
    static Map<Integer, ArrayList<Integer>> map = new HashMap<>();
    static boolean[] visited;
    
    public int solution(String begin, String target, String[] words) {
        int answer = 0;
     
        visited = new boolean[words.length];
        
        toMap(words);
        
        return bfs(begin, target, words);
        //한개만 다르면 연결되어 있음
        
    }
    
    public void toMap(String[] words) {
        
        for(int i = 0 ; i < words.length; i++) {
            map.put(i, new ArrayList<>());
        }
        
        for(int i = 0 ; i < words.length - 1; i++) {
            
            String a = words[i];
            
            for(int j = i + 1 ; j < words.length; j++) {
                String b = words[j];
                
                int count = 0;
                for(int k = 0; k < a.length(); k++) {
                    if (a.charAt(k) != b.charAt(k))
                        count++;
                }
                
                if (count == 1) {
                    map.get(i).add(j);
                    map.get(j).add(i);
                }
            }
        }
        
    }
    
    public int bfs(String begin, String target, String[] words) {
        
        Deque<Node> queue = startDeque(begin, words);
        
        while (!queue.isEmpty()) {
            
            Node poll = queue.pollFirst();
            
            if (words[poll.i].equals(target))
                return poll.w;
            
            ArrayList<Integer> linked = map.get(poll.i);
            
            for(int i = 0 ; i < linked.size(); i++) {
                
                if (!visited[linked.get(i)]) {
                    queue.add(new Node(linked.get(i), poll.w + 1));
                    visited[linked.get(i)] = true;
                }
            }
        }
        
        return 0;
        
    }
    
    public Deque<Node> startDeque(String begin, String[] words) {
        Deque<Node> queue = new ArrayDeque<>();
        
        for(int i = 0 ; i < words.length; i++) {
            
            int count = 0;
            for (int j = 0 ; j < begin.length(); j++) {
                if (begin.charAt(j) != words[i].charAt(j))
                    count++;
            }
            
            if(count == 1) {
                queue.add(new Node(i, 1));
                visited[i] = true;
            }
                
        }
        
        return queue;
    }
    
    public class Node {
        int i, w;
        
        public Node (int i, int w) {
            this.i = i;
            this.w = w;
        }
    }
}