단어 변환 (프로그래머스) [JAVA]
반응형

 

문제

문제 링크 : 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

 

풀이

BFS를 활용해서 풀었다. 정답까지 향하는 최단 경로를 check하는 경우이기 때문.

(DFS는 경로가 가능한지 찾아볼 때. BFS는 최단 경로를 찾아볼 때)

다만 경로가 동점일 때에는 Index가 빠른 경우가 출력된다는 단점이 있다.

우선 두 word에서의 변환이 가능한지 확인하는 canChange()를 구현하였다. (알파벳 1개만 달라야 가능)

Word를 Index단위로 사용해서 (begin = -1) 큐에 begin을 넣고 BFS로 탐색한다.

이때 Queue의 size를 미리 저장해서 for문으로 체크하면서 깊이를 체크한다. (1깊이당 1변환)

(Queue = First In First Out)

Queue가 비어있을 때 (더이상 변환 불가능) or 정답을 찾으면 종료.

시간 복잡도는 최악의 경우 그래프의 노드를 V, 가능한 경로를 E라 할때 $O(V+E)$

완전 그래프일때는 $O(N^2)$이라 할 수 있다.

 

코드

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
class Solution {
    public int solution(String begin, String target, String[] words) {
        int answer = 0;
        Queue<Integer> q = new LinkedList<Integer>();
    	
    	//방문했는지 체크
    	int[] checked = new int[words.length];
    	for(int i=0; i<checked.length; i++){
           checked[i] = 0; 
        } 
    	q.add(-1); //-1 = begin
    	
    	while(!q.isEmpty()){
    		int sz = q.size();
            //size만큼 사이클을 돌면 1번 깊이라고 생각 -> 1번 이동하였다.
    		for(int a =0; a<sz; a++){
    			int s = q.poll();
        		String key;
        		
        		if(s == -1) key = begin;
        		else{
        			key = words[s];
        			
        			if(key.equals(target)){
        				return answer; //맞으면 바로 answer 보내기
        			}
        			//방문 한거였으면 넘어감.
        			if(checked[s] != 0) continue;
        			checked[s] = 1; //방문했다고 표시
        		}
        		for(int i=0; i<words.length; i++){
        			if(canChange(key, words[i])) q.add(i);
        		}
    		}
    		answer++;
    	}	
        return 0; //성공 못하면 0
    }
    //알파벳이 한개만 다른지 확인
    public boolean canChange(String src, String des){
    	int count = 0;
    	for(int i=0; i<src.length(); i++){
    		if(src.charAt(i) != des.charAt(i)) count++;
    		if(count > 1){
    			return false;
    		}
    	}
    	return true;	
    }
}

 

결과

 

전문가가 아니라 정확하지 않은 지식이 담겨있을 수 있습니다.
언제든지 댓글로 의견을 남겨주세요!

 

반응형