메모리: 135 MB, 시간: 773.04 ms
코딩테스트 연습 > 연습문제
정확성: 100.0
합계: 100.0 / 100.0
강철부대의 각 부대원이 여러 지역에 뿔뿔이 흩어져 특수 임무를 수행 중입니다. 지도에서 강철부대가 위치한 지역을 포함한 각 지역은 유일한 번호로 구분되며, 두 지역 간의 길을 통과하는 데 걸리는 시간은 모두 1로 동일합니다. 임무를 수행한 각 부대원은 지도 정보를 이용하여 최단시간에 부대로 복귀하고자 합니다. 다만 적군의 방해로 인해, 임무의 시작 때와 다르게 되돌아오는 경로가 없어져 복귀가 불가능한 부대원도 있을 수 있습니다.
강철부대가 위치한 지역을 포함한 총지역의 수 n, 두 지역을 왕복할 수 있는 길 정보를 담은 2차원 정수 배열 roads, 각 부대원이 위치한 서로 다른 지역들을 나타내는 정수 배열 sources, 강철부대의 지역 destination이 주어졌을 때, 주어진 sources의 원소 순서대로 강철부대로 복귀할 수 있는 최단시간을 담은 배열을 return하는 solution 함수를 완성해주세요. 복귀가 불가능한 경우 해당 부대원의 최단시간은 -1입니다.
n ≤ 100,000
n까지의 번호로 구분됩니다.roads의 길이 ≤ 500,000
roads의 원소의 길이 = 2roads의 원소는 [a, b] 형태로 두 지역 a, b가 서로 왕복할 수 있음을 의미합니다.(1 ≤ a, b ≤ n, a ≠ b)sources의 길이 ≤ 500
sources[i] ≤ ndestination ≤ n| n | roads | sources | destination | result |
|---|---|---|---|---|
| 3 | [[1, 2], [2, 3]] | [2, 3] | 1 | [1, 2] |
| 5 | [[1, 2], [1, 4], [2, 4], [2, 5], [4, 5]] | [1, 3, 5] | 5 | [2, -1, 0] |
입출력 예 #1
입출력 예 #2
출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
이 문제는 여러 부대원들이 흩어져 있는 위치(sources)에서 강철부대 본부(destination)로 복귀하는 최단 시간을 계산하는 문제입니다.
n: 총 지역의 수 (노드의 개수).roads: 두 지역을 연결하는 길 정보 (양방향 간선, 가중치 1).sources: 최단 시간을 구해야 하는 출발 지역 목록.destination: 목표 도착 지역 (부대).sources에 주어진 순서대로 각 지역에서 destination까지의 최단 시간을 담은 배열을 반환합니다. 복귀 불가능 시 -1을 반환합니다.이 문제는 가중치가 1인 그래프에서 최단 거리를 찾는 전형적인 최단 경로 문제입니다.
알고리즘 선택: 가중치가 모두 1인 최단 경로 문제에서는 다익스트라 알고리즘보다 훨씬 효율적인 **너비 우선 탐색(Breadth-First Search, BFS)**을 사용하는 것이 가장 적합합니다. BFS는 시작점에서부터 거리를 층별로 탐색하며 최단 거리를 보장합니다.
효율적인 탐색 전략 (핵심):
sources의 크기는 최대 500개입니다. 만약 각 source마다 destination까지의 최단 거리를 구하기 위해 BFS를 개별적으로 실행한다면 최대 500번의 탐색을 해야 합니다.sources에서 destination으로 가는 경로를 찾는 대신, destination을 시작점으로 단 한 번의 BFS를 실행하여 모든 지역까지의 최단 거리를 한 번에 계산합니다. 이 결과를 이용하여 각 source의 최단 거리를 즉시 찾아낼 수 있습니다.n개의 지역을 표현하는 인접 리스트(adjacency list, graph)를 0부터 $n-1$까지의 인덱스로 초기화합니다.x, y = i[0]-1, i[1]-1).roads 배열을 순회하면서 양방향 간선을 graph에 추가합니다. ([a, b]가 주어지면, graph[a-1]에 b-1을, graph[b-1]에 a-1을 추가).BFS(graph, dest) 함수를 호출하여 최단 거리를 계산합니다. 이때 시작점 dest는 destination-1입니다.dist 배열을 $n$ 크기로 초기화하며, 모든 값을 -1로 설정합니다. -1은 해당 지역에 도달할 수 없음을 의미합니다.dest)의 거리는 0으로 설정하고, 탐색을 위한 큐(stack, deque 사용)에 시작점을 넣습니다.x를 큐에서 꺼냅니다.x와 연결된 모든 이웃 노드 i를 확인합니다.i의 dist[i]가 아직 -1이라면 (즉, 아직 방문하지 않았다면):
dist[i]를 dist[x] + 1로 업데이트하고 (최단 거리 갱신), i를 큐에 넣습니다.dist 배열에는 destination에서부터 모든 지역까지의 최단 거리가 저장됩니다.solution 함수는 sources 배열을 순회합니다.i에 대해, BFS 결과 배열 arr에서 해당 지역의 최단 거리를 조회합니다 (arr[i-1]).answer 배열에 순서대로 추가하여 반환합니다. 만약 복귀 불가능한 지역이라면 arr[i-1]은 -1일 것이므로, 그대로 결과에 반영됩니다.시간 복잡도:
sources 배열을 순회하며 결과를 찾는 데 $O(S)$ 시간이 소요됩니다.총 시간 복잡도는 $O(M + N + S)$입니다. $N$과 $M$이 $S$보다 훨씬 크므로, 전체적으로 **$O(N + M)$**의 매우 효율적인 성능을 가집니다.
공간 복잡도:
graph: 인접 리스트를 저장하는 데 $O(N + M)$ 공간이 필요합니다.dist: 거리를 저장하는 배열로 $O(N)$ 공간이 필요합니다.stack (큐): 최악의 경우 모든 노드를 저장할 수 있으므로 $O(N)$ 공간이 필요합니다.총 공간 복잡도는 **$O(N + M)$**입니다.
sources)에서 하나의 목적지(destination)로 가는 최단 경로를 구해야 하지만, 그래프가 양방향이므로, 목적지(destination)에서 출발하여 모든 노드까지의 최단 거리를 단 한 번의 BFS로 계산합니다.from collections import deque
def solution(n, roads, sources, destination):
answer = []
graph = [[] for i in range(n)]
for i in roads:
x,y = i[0]-1,i[1]-1
graph[x].append(y)
graph[y].append(x)
arr=BFS(graph,destination-1)
answer=[]
for i in sources:
answer.append(arr[i-1])
return answer
def BFS(graph, dest):
stack = deque([dest])
dist = [-1 for i in range(len(graph))]
dist[dest] = 0
while stack:
x = stack.popleft()
for i in graph[x]:
if dist[i] == -1:
dist[i] = dist[x]+1
stack.append(i)
return dist