Coding Interview Prep · 강의

네트워크 지연 시간과 경로 복원

다익스트라 알고리즘으로 네트워크 지연 시간 문제를 해결하고, 이전 노드 맵으로 실제 최단 경로를 복원하며, 대규모 그래프에서 양방향 BFS를 살펴봅니다.

레슨 4/413개 단계

네트워크 지연 시간과 경로 복원은(는) CoddyKit의 무료 Coding Interview Prep 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Coding Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

네트워크 지연 시간 문제

네트워크 지연 시간(LeetCode 743) 문제에서는 신호 이동 시간을 나타내는 방향 가중 간선과 n개의 노드로 구성된 네트워크가 주어집니다. 노드 k에서 보낸 신호가 모든 노드에 도달하는 최소 시간을 구해야 합니다. 도달할 수 없는 노드가 있으면 -1을 반환합니다. 이는 다익스트라의 직접적인 응용으로, 답은 k에서 모든 노드까지의 최단 경로 거리 중 최댓값입니다.

해법: 다익스트라 + 거리의 최댓값

출발점 k에서 다익스트라를 실행하여 모든 노드 v에 대한 dist[v]를 구합니다. 답은 max(dist.values())입니다. 어떤 dist[v]가 여전히 inf라면 해당 노드에 도달할 수 없다는 뜻이므로 -1을 반환합니다. 신호는 모든 경로를 동시에 따라가므로, 병목은 도달하는 데 가장 오래 걸리는 노드입니다.

import heapq
from collections import defaultdict

def networkDelayTime(times, n, k):
    graph = defaultdict(list)
    for u, v, w in times:
        graph[u].append((v, w))
    
    dist = {i: float('inf') for i in range(1, n+1)}
    dist[k] = 0
    heap = [(0, k)]
    
    while heap:
        d, u = heapq.heappop(heap)
        if d > dist[u]:
            continue
        for v, w in graph[u]:
            if dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                heapq.heappush(heap, (dist[v], v))
    
    ans = max(dist.values())
    return ans if ans < float('inf') else -1

print(networkDelayTime([[2,1,1],[2,3,1],[3,4,1]], 4, 2))  # 2

이전 노드 배열을 사용한 경로 복원

거리를 계산하면서 실제 최단 경로도 복원하려면 각 노드의 최적 이전 노드를 기록하는 prev 딕셔너리를 유지합니다. dist[v]를 갱신할 때마다 prev[v] = u로 설정합니다. 다익스트라가 끝나면 도착점에서 시작하여 prev 포인터를 따라 출발점에 도달할 때까지 거꾸로 추적한 다음, 순서를 뒤집어 정방향 경로를 얻습니다.

import heapq
from collections import defaultdict

def shortest_path_with_reconstruction(times, n, src, dst):
    graph = defaultdict(list)
    for u, v, w in times:
        graph[u].append((v, w))
    
    dist = {i: float('inf') for i in range(1, n+1)}
    prev = {i: None for i in range(1, n+1)}
    dist[src] = 0
    heap = [(0, src)]
    
    while heap:
        d, u = heapq.heappop(heap)
        if d > dist[u]: continue
        for v, w in graph[u]:
            if dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                prev[v] = u
                heapq.heappush(heap, (dist[v], v))
    
    # Reconstruct path from src to dst
    path, node = [], dst
    while node is not None:
        path.append(node)
        node = prev[node]
    return dist[dst], path[::-1]

큰 무가중치 그래프를 위한 양방향 BFS

하나의 출발점과 도착점 쌍만 필요한 큰 무가중치 그래프에서는 양방향 BFS가 일반 BFS보다 훨씬 빠를 수 있습니다. 출발점과 도착점에서 동시에 BFS를 실행하고 두 탐색 전선이 만날 때 중단합니다. 각 전선은 그래프 깊이의 절반만 탐색하면 되므로 실제 속도 향상 효과가 큽니다. 이때 탐색하는 노드 수가 O(b^d)에서 O(2 × b^(d/2))로 줄어들며, b는 분기 계수입니다.

from collections import deque

def bidir_bfs(graph, src, dst):
    if src == dst: return 0
    
    front_q = deque([src]); front_visited = {src: 0}
    back_q = deque([dst]);  back_visited = {dst: 0}
    
    def expand(queue, visited, other_visited):
        node = queue.popleft()
        for nxt in graph[node]:
            if nxt not in visited:
                visited[nxt] = visited[node] + 1
                queue.append(nxt)
                if nxt in other_visited:
                    return visited[nxt] + other_visited[nxt]
        return -1
    
    while front_q or back_q:
        res = expand(front_q, front_visited, back_visited)
        if res != -1: return res
        res = expand(back_q, back_visited, front_visited)
        if res != -1: return res
    return -1

어떤 알고리즘을 선택할까

선택 가이드: 무가중치 그래프, 단일 쌍 → BFS 또는 양방향 BFS. 가중치가 있고 음수가 아님, 단일 출발점 → 다익스트라. 가중치가 있고 음수일 수 있음, 단일 출발점 → 벨만-포드. 모든 쌍 → 플로이드-워셜(작은 V) 또는 V × 다익스트라(희소 그래프). 홉 수 제한 → 패스 수를 제한한 수정된 벨만-포드. 면접에서 이러한 선택 근거를 소리 내어 설명하면 알고리즘에 대한 숙련도를 보여 줄 수 있습니다.

도달 가능한 이웃이 가장 적은 도시 찾기 (LeetCode 1334)

가중치가 있는 경로와 distanceThreshold가 주어질 때, 임계값 이내에서 다른 도시 중 도달 가능한 도시 수가 가장 적은 도시를 찾습니다(동률이면 도시 인덱스가 더 큰 도시를 선택합니다). 해법은 플로이드-워셜로 모든 정점 쌍 사이의 최단 경로를 계산한 다음, 각 도시에 대해 임계값 이내에서 도달 가능한 다른 도시의 수를 세는 것입니다. 개수가 최소인 도시를 반환하며, 동률이면 인덱스가 가장 큰 도시를 반환합니다.

def findTheCity(n, edges, distanceThreshold):
    INF = float('inf')
    dist = [[INF]*n for _ in range(n)]
    for i in range(n): dist[i][i] = 0
    for u, v, w in edges:
        dist[u][v] = dist[v][u] = w
    for k in range(n):
        for i in range(n):
            for j in range(n):
                dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j])
    
    best_city, best_count = -1, n
    for city in range(n):
        count = sum(1 for j in range(n) if j != city and dist[city][j] <= distanceThreshold)
        if count <= best_count:
            best_count = count
            best_city = city
    return best_city

print(findTheCity(4,[[0,1,3],[1,2,1],[1,3,4],[2,3,1]],4))  # 3

가중치가 있는 DAG의 경로

유향 비순환 그래프(DAG)에서는 위상 정렬과 완화를 사용하여 O(V+E)에 최단 경로 또는 최장 경로를 구할 수 있으며, 이는 다익스트라보다 빠릅니다. 노드를 위상 순서대로 처리하고, 노드 u를 처리할 때 모든 나가는 간선을 완화합니다. 최장 경로를 구할 때는(프로젝트 일정 관리나 임계 경로에 유용합니다) 가중치의 부호를 바꾸거나 min을 max로 변경합니다.

from collections import deque

def dag_shortest_path(V, edges, source):
    graph = [[] for _ in range(V)]
    in_degree = [0] * V
    for u, v, w in edges:
        graph[u].append((v, w))
        in_degree[v] += 1
    # Topological sort (Kahn's)
    queue = deque(i for i in range(V) if in_degree[i] == 0)
    topo = []
    while queue:
        node = queue.popleft(); topo.append(node)
        for nxt, _ in graph[node]:
            in_degree[nxt] -= 1
            if in_degree[nxt] == 0: queue.append(nxt)
    # Relax in topological order
    dist = [float('inf')] * V
    dist[source] = 0
    for u in topo:
        if dist[u] != float('inf'):
            for v, w in graph[u]:
                dist[v] = min(dist[v], dist[u] + w)
    return dist

장애물이 있는 행렬에서의 최단 경로

자주 나오는 면접 변형 문제는 일부 칸이 막혀 있는 2차원 격자에서 왼쪽 위에서 오른쪽 아래까지의 최단 경로를 찾는 것입니다. 각 이동 비용이 1이므로 이는 무가중치 BFS 문제입니다. 네 방향으로 이동하는 BFS를 사용하고, 다시 방문하지 않도록 큐에서 꺼낼 때가 아니라 큐에 넣을 때 칸을 방문 처리하십시오. 장애물을 비용을 지불하고 통과할 수 있다면 2차원 격자를 가중치 그래프로 보고 다익스트라를 사용합니다.

from collections import deque

def shortest_path_binary_matrix(grid):
    n = len(grid)
    if grid[0][0] == 1 or grid[n-1][n-1] == 1:
        return -1
    queue = deque([(0, 0, 1)])  # (row, col, distance)
    visited = {(0, 0)}
    dirs = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
    while queue:
        r, c, d = queue.popleft()
        if r == n-1 and c == n-1:
            return d
        for dr, dc in dirs:
            nr, nc = r+dr, c+dc
            if 0<=nr<n and 0<=nc<n and grid[nr][nc]==0 and (nr,nc) not in visited:
                visited.add((nr,nc))
                queue.append((nr, nc, d+1))
    return -1

print(shortest_path_binary_matrix([[0,0,0],[1,1,0],[1,1,0]]))  # 4

다중 시작점 BFS

여러 시작점이 존재할 때(예: 격자에 여러 개의 ‘관문’이 있거나 지도에 여러 출발점이 있을 때)는 다중 시작점 BFS를 실행합니다. 모든 시작점을 거리 0으로 동시에 큐에 넣습니다. 그러면 한 번의 BFS 순회로 가장 가까운 시작점에서 모든 칸까지의 최단 거리를 계산할 수 있습니다. 이 기법은 각 시작점에서 BFS를 따로 실행할 필요를 없애며, 전체 복잡도는 O(V+E)입니다.

알고리즘 선택 요약

간결한 선택 트리는 다음과 같습니다. 단일 출발점, 음이 아닌 가중치 → 다익스트라 O((V+E) log V). 단일 출발점, 음의 가중치 → 벨만-포드 O(VE). 모든 쌍, 작은 V → 플로이드-워셜 O(V³). DAG, 모든 가중치 → 위상 정렬 + 완화 O(V+E). 무가중치 → BFS O(V+E). 격자 경로 → BFS(무가중치) 또는 힙을 사용하는 다익스트라(가중치). 이 표를 외워 두십시오. 어떤 최단 경로 면접에서도 이어지는 질문에 답하는 데 도움이 됩니다.

면접 질문에서의 경로 찾기

많은 면접 문제는 비용뿐 아니라 실제 경로를 요구합니다. 항상 다음을 확인하십시오. 경로가 필요한가요, 아니면 거리만 필요한가요? 경로가 필요하다면 처음부터 prev 딕셔너리를 할당합니다. 흔한 실수는 종료 조건으로 prev[source] = None을 초기화하지 않는 것과 복원 순서를 혼동하는 것입니다. 즉, 도착점에서 출발점까지 거꾸로 추적한 다음 순서를 뒤집어야 합니다. 더 큰 문제에 적용하기 전에 3~4개 노드로 이루어진 예제에서 경로 복원을 연습하십시오.

빠른 확인

이 수업에서 다룬 자료 구조 및 알고리즘 — 코딩 면접 준비 개념에 대한 이해도를 확인해 보십시오.

수업 요약

이 수업에서는 다음을 배웠습니다. 네트워크 지연 시간의 답은 다익스트라를 실행한 후 max(dist.values())로 구할 수 있습니다. 경로 복원에서는 dist[v]가 개선될 때마다 이전 노드 배열을 갱신합니다. 또한 양방향 BFS는 한 쌍의 정점을 잇는 무가중치 최단 경로에서 탐색 공간을 절반으로 줄일 수 있습니다. 다음에는 위상 정렬을 위한 칸 알고리즘을 사용하여 그래프의 순서 정하기를 살펴보겠습니다.

무료로 시작

AI 튜터와 함께 Coding Interview Prep을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
90
레슨
360

자주 묻는 질문

“네트워크 지연 시간과 경로 복원” 강의는 무료인가요?

네 — “네트워크 지연 시간과 경로 복원” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Coding Interview Prep 강의 전체를 잠금 해제할 수 있습니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

“네트워크 지연 시간과 경로 복원”에서 뭘 배우나요?

다익스트라 알고리즘으로 네트워크 지연 시간 문제를 해결하고, 이전 노드 맵으로 실제 최단 경로를 복원하며, 대규모 그래프에서 양방향 BFS를 살펴봅니다. 브라우저에서 직접 실행하는 실습 코드로 Coding Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Coding Interview Prep을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Coding Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“네트워크 지연 시간과 경로 복원” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Coding Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Coding Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 우선순위 큐를 사용하는 다익스트라 알고리즘
  2. 벨만-포드와 음수 사이클
  3. 플로이드-워셜: 모든 쌍의 최단 경로
  4. 네트워크 지연 시간과 경로 복원
← Coding Interview Prep(으)로 돌아가기