새소식

반응형
코딩 테스트

[프로그래머스] 여행경로

  • -
728x90
반응형

문제

  • [출발지, 도착지]의 항공권들을 모두 이용해 여행경로 짜기
    • 항상 "ICN" 공항에서 출발
    • 3 <= 공항의 개수 <= 10,000
  • 가능한 경로가 2개 이상일 경우 알파벳 순서가 앞서는 경로를 리턴하기

 

풀이 1

  • 딕셔너리에 {출발지 : 도착지} 저장하기
    • 도착지가 여러개인 경우 알파벳 순으로 정렬하기
  • ICN 부터 차례로 경로 추가하기
1,2 번 런타임 에러 발생

알파벳 순서로만 경로를 추가하면 모든 티켓을 사용해서 경로 완성이 불가능한 경우의 수가 존재하는 것 같다.

 

from collections import defaultdict

def solution(tickets):
	# {출발지 : [도착지]} 저장하기
    graph = defaultdict(list)
    for s, e in tickets:
        graph[s].append(e)
    
    for k in graph:	# 도착지가 여러개면 알파벳 순으로 정렬
        graph[k].sort(reverse=True)
    
    n = len(tickets)
	answer = ["ICN", ]
    for _ in range(n): 
    	now = answer[-1]
        now = graph[now].pop()
        answer.append(now)
    
    return answer

 

풀이 2

  • BFS 이용해 모든 티켓을 사용한 경우에만 경로를 추가하도록 한다.
from collections import deque
def solution(tickets):
    answer = []
    # (현재 위치, 지금까지 경로, 사용 가능한 티켓 번호)
    q = deque([("ICN", ["ICN"], set([i for i in range(len(tickets))]))])
    
    while q:
        now, path, visitable = q.popleft()
		
        # 모든 티켓 사용하면 해당 경로 추가하기
        if not visitable:
            answer.append(path)
        
        # 사용 가능한 티켓이고, 시작 위치가 현재 위치와 가능한 경우
        for idx in visitable:
            start, dest = tickets[idx]
            if start == now :
                q.append((dest, path+[dest], visitable-{idx}))
                
    return sorted(answer)[0]

 

풀이 3

  • DFS 사용해서 모든 경로를 확인하지 않고, 단 하나의 경로만 확인하기
  • 알파벳 순으로 갔다가, 불가능한 경로일 때 다시 되돌아와야 한다.
    • stack으로 현재 경로를 저장하고, 다음에 갈 수 있는 경로를 알파벳 순서로 추가한다.
    • 마지막에 도달했을 때(다음에 갈 수 있는 경로가 없을 때) 해당 위치를 정답 경로에 추가한다.
      • 갈 수 있는 경로가 없다는 뜻은 해당 위치가 '마지막' 이라는 의미다.
from collections import defaultdict

def solution(tickets):
	# {출발지 : [도착지]} 저장하기
    graph = defaultdict(list)
    for s, e in tickets:
        graph[s].append(e)
    
    for k in graph:	# 도착지가 여러개면 알파벳 순으로 정렬
        graph[k].sort(reverse=True)
    
    n = len(tickets)
    now = "ICN"
    stack = ["ICN"] # 현재 경로
    answer = []     # 정답 경로
    while stack :
        now = stack[-1]     # 현재 위치
        # 현재 위치에서 다음에 갈 수 있는 경로가 없을 때, 
        # 즉 마지막 위치를 정답 경로에 추가하기
        if now not in graph or not graph[now]:
            answer.append(stack.pop())
        # 다음에 갈 수 있는 경로가 있으면 알파벳 순서로 추가하기
        else:
            stack.append(graph[now].pop())
    
    return answer[::-1]

 

그림으로 이해하기

더보기

a 에서 시작하고, 예시의 경로가 정답인 경우를 살펴보자.

stack 에는 a 가 들어있다. (문제에서는 시작점인 ICN)

 

 

graph[a]의 마지막 원소인 c를 꺼낸 뒤 stack에 추가한다.

 

graph[c]의 원소인 e를 꺼낸 뒤 stack에 추가한다.

 

 

grpah 에는 e 라는 키가 없다. 따라서 e를 꺼낸 뒤 answer에 추가한다.

 

grpah[c] 는 빈 리스트이다. 따라서 c를 꺼낸 뒤 answer에 추가한다.

 

 

graph[a]의 원소인 d를 꺼낸 뒤 stack에 추가한다.

 

graph[d]의 원소인 b를 꺼낸 뒤 stack에 추가한다.

 

graph[b]의 원소인 a를 꺼낸 뒤 stack에 추가한다.

 

grpah[a] 는 빈 리스트이다. 따라서 a를 꺼낸 뒤 answer에 추가한다.

 

마찬가지로 모두 빈리스트이므로 b, d, a 순서대로 answer에 추가한다.

 

이렇게 다음 경로가 없을 때가 가장 마지막에 들어가야 하는 위치가 된다. answer를 거꾸로 뒤집어 리턴하면 여행경로가 된다.

 

 

 

 

References

  • 프로그래머스 고득점Kit BFS/DFS

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.