문제 설명
주어진 항공권을 모두 이용하여 여행경로를 짜려고 합니다. 항상 "ICN" 공항에서 출발합니다.
항공권 정보가 담긴 2차원 배열 tickets가 매개변수로 주어질 때, 방문하는 공항 경로를 배열에 담아 return 하도록 solution 함수를 작성해주세요.
제한사항
- 모든 공항은 알파벳 대문자 3글자로 이루어집니다.
- 주어진 공항 수는 3개 이상 10,000개 이하입니다.
- tickets의 각 행 [a, b]는 a 공항에서 b 공항으로 가는 항공권이 있다는 의미입니다.
- 주어진 항공권은 모두 사용해야 합니다.
- 만일 가능한 경로가 2개 이상일 경우 알파벳 순서가 앞서는 경로를 return 합니다.
- 모든 도시를 방문할 수 없는 경우는 주어지지 않습니다.
입출력 예
ticketsreturn
[["ICN", "JFK"], ["HND", "IAD"], ["JFK", "HND"]] | ["ICN", "JFK", "HND", "IAD"] |
[["ICN", "SFO"], ["ICN", "ATL"], ["SFO", "ATL"], ["ATL", "ICN"], ["ATL","SFO"]] | ["ICN", "ATL", "ICN", "SFO", "ATL", "SFO"] |
입출력 예 설명
예제 #1
["ICN", "JFK", "HND", "IAD"] 순으로 방문할 수 있습니다.
예제 #2
["ICN", "SFO", "ATL", "ICN", "ATL", "SFO"] 순으로 방문할 수도 있지만 ["ICN", "ATL", "ICN", "SFO", "ATL", "SFO"] 가 알파벳 순으로 앞섭니다.
해결 방법
1. 모든 항공권을 사용해야한다.
2. 경로만 찾으면 되므로 DFS로 탐색, 항공권이 남았음에도 탐색이 불 가능하면 다른 노드 탐색
3. tickets[1]을 키 값으로 알파벳 정렬
실패한 풀이
def dfs(location, usedTickets, tickets):
if len(tickets) == 0: # 티켓 모두 사용
return location
functionContinue = False
for s, e in tickets:
if location[-1] == s: # 갈 수 있으며 사용안했다면
tempLocation = location[0:]
tempLocation.append(e)
tempUsedTickets = usedTickets[0:]
tempUsedTickets.append([s, e])
tempTickets = tickets[0:]
tempTickets.remove([s, e])
return dfs(tempLocation, tempUsedTickets, tempTickets)
for l in tickets:
if l not in usedTickets:
functionContinue = True
if functionContinue == False:
return location
# 만약 갈 수 없다면
tempLocation = location[:-1]
tempTickets = tickets[0:]
tempTickets.append([location[-2], location[-1]])
tempUsedTickets = usedTickets[0:]
return dfs(tempLocation, tempUsedTickets, tempTickets)
def solution(tickets):
tickets.sort(key=lambda x: (x[0], x[1]))
for s, e in tickets:
if s == "ICN": # ICN에서 시작
tickets.remove([s, e])
return dfs([s, e], [s, e], tickets)
print(solution([["ICN", "COO"], ["COO", "ICN"], ["COO", "ICN"]]))
테스트 케이스1에서 런타임 에러가 계속 발생했다.
다른 유저들의 질문을 보니 중복 티켓이 존재하는 경우는 티켓이 남아있어도 된다는데 반례로 이 부분을 해결했지만
결국 테스트 케이스1의 런타임 에러를 해결하지 못했다....
아마도 중복이 문제가 아닌가보다.
올바른 풀이
def solution(tickets):
routes = {}
for t in tickets:
routes[t[0]] = routes.get(t[0], []) + [t[1]]
for r in routes:
routes[r].sort(reverse=True)
stack = ['ICN']
path = []
while stack:
top = stack[-1]
if top in routes and routes[top]:
stack.append(routes[top].pop())
else:
path.append(stack.pop())
return path[::-1]
tickets를 dic로 정리해 처리했다. 중복에 대한 문제를 해결함과 동시에 시간복잡도도 훨씬 좋다.
더 이상 갈 수 없는 경우, path에 stack 요소가 pop되어 저장되는데 더 이상 갈 수 없다는 것은 마지막 요소라는걸 의미하기 때문이다.
즉, 최종 도착지가 되어야한다는 것이다. 따라서 pop 후 경로의 맨 마지막에 저장해준다.
정확히 이해하지 못해서 leetcode의 비슷한 문제를 풀어보려한다.
https://leetcode.com/problems/reconstruct-itinerary/
'Programming > Algorithm' 카테고리의 다른 글
[백준] 1003 피보나치 함수 (0) | 2021.08.14 |
---|---|
[Python/알고리즘] 다단계 칫솔 판매 (Lv.3) (0) | 2021.08.04 |
[Python/알고리즘] DFS : 네트워크 (프로그래머스) (0) | 2021.07.18 |
[Python/알고리즘] BFS : 타겟 넘버 (프로그래머스) (0) | 2021.07.18 |
[Python/알고리즘] BFS : 단어변환 (프로그래머스) (2) | 2021.07.18 |