본문 바로가기
프로그래머스/Lv.3

[프로그래머스 Lv.3][DFS/BFS] 단어 변환 (python)

by 똥먹는낙타 2022. 12. 19.
728x90
반응형

문제 설명

두 개의 단어 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 합니다.
입출력 예begintargetwordsreturn
"hit" "cog" ["hot", "dot", "dog", "lot", "log", "cog"] 4
"hit" "cog" ["hot", "dot", "dog", "lot", "log"] 0
입출력 예 설명

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

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

 

 Code (예시 테스트 케이스 실패 / 제출은 통과 ... ?)

from collections import deque

def bfs(start, target, words):
    queue = deque()
    count = 0
    queue.append(start)
    visited = [0] * len(words)
    
    while queue:
        v = queue.popleft()
        if v == target:
            return count
        
        for i in range(len(words)):
            cnt = 0
            if visited[i] == 0:
                for j in range(len(v)):
                    if v[j] != words[i][j]:
                        cnt += 1
                        
                if cnt == 1:
                    visited[i] = 1
                    queue.append(words[i])
                    count += 1
    
    return 0
                
    
def solution(begin, target, words):
    answer = bfs(begin, target, words)
    
    return answer

 
가장 짧은 변환 과정을 구하는 문제이기에 bfs로 구현했다. 예시 테스트 케이스 1 통과에 실패했으나 그냥 제출이나 해볼까하고 제출 눌렀더니 정답입니다! 가 떠서 정말 당황.... 올바른 풀이는 아닌 것 같다. 내가 작성한 코드처럼 문자가 1개만 다를 때 마다 queue.append 해주면서 계속 count ++ 해주게 되면 테스트 케이스 1의 경우처럼 다른 카운트가 나와 틀린 답을 도출할 위험이 있다.. 따라서 구글링을 통해 참고한 코드로 재제출하였다.

✔️ Code

from collections import deque

def bfs(start, target, words):
    queue = deque()
    queue.append([start, 0])
    visited = [0] * len(words)
    
    while queue:
        v, count = queue.popleft()
        if v == target:
            return count
        
        for i in range(len(words)):
            cnt = 0
            if visited[i] == 0:
                for j in range(len(v)):
                    if v[j] != words[i][j]:
                        cnt += 1
                        
                if cnt == 1:
                    visited[i] = 1
                    queue.append([words[i], count + 1])
    
    return 0
                
    
def solution(begin, target, words):
    answer = bfs(begin, target, words)
    
    return answer

 

✏️ Comment

위에 내가 작성한 코드와 다른 점은 바로 queue에 문자만 집어넣는 것이 아니라 "count"도 같이 집어넣어주는 것이다. 
queue.append([start, 0]) 을 초기값으로 넣어준 후 하나씩 popleft() 하면서 문자열 비교를 수행한다. 
다른 문자의 개수가 1개라면 queue에 집어넣어주고 방문여부를 체크해준다.
이때, queue.append([words[i], count + 1]) 을 해주어야 한다.

아래에 테스트 케이스 1에 대한 작동 방식?을 그림으로 그려보았다. 오른쪽에 적어놓은 숫자들은 내가 작성했던 틀린 코드의 count 결과이다. 해당 코드를 실행할 경우 테스트 케이스 1의 답이 6이 나오게 된다.
그림으로 그려보니 훨씬 수월하게 이해할 수 있었다. 사람들은 어떻게 카운트도 같이 queue에 넣을 생각을 하는 걸까.. 흑흑

 

728x90
반응형

댓글