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;
}
}
'Level-Up > 알고리즘' 카테고리의 다른 글
[프로그래머스] 로또의 최고 순위와 최저 순위 - Lv.1 (0) | 2022.04.15 |
---|---|
[프로그래머스] 신고 결과 받기 - Lv.1 (0) | 2022.04.14 |
[백준] 12865. 평범한 배낭 - 골드5 (0) | 2022.03.22 |
[프로그래머스] 네트워크 / BFS - Lv.3 (0) | 2022.03.17 |
[백준] 17140. 이차원 배열과 연산 - 골드4 (0) | 2022.03.17 |