Shortest Paths & Dijkstra
- Choose between breadth-first search, a 0-1 deque and Dijkstra by asking what one step costs
- Run Dijkstra on a score that is a minimum along the path, with a max-heap and a precomputed grid
- Explain why negative costs break Dijkstra and when the right-and-down grid DP still holds
Uber routes cars over a road network where every street has a travel time, so its graph questions rarely stay unweighted for long. The problems here start like the breadth-first search in the Graphs lesson, then change what a step costs, and sometimes what a node is. In Bus Routes a node is a whole route, and one hop means one more bus. The safest-path grid prices each cell by its distance to the nearest thief before any path search starts. Minimum Path Sum opens as a grid DP and stops being one once the walker can move up or left.
Before you choose a search, say what a single step costs and whether that cost can ever go down along a path. Equal costs mean BFS. Costs of zero or one mean a deque, and any other non-negative cost means Dijkstra with a heap. A negative cost rules Dijkstra out entirely, and that's the turn Minimum Path Sum likes to take.
Matching the search to the cost of a step
Breadth-first search finds the fewest hops because it finishes every state at distance d before it touches distance d + 1. Weights break that. A two-hop route through cheap streets can beat a one-hop route along an expensive one, so the ring order no longer matches the cost order. Dijkstra restores it with a min-heap keyed on cost so far. Each pop is the cheapest state not yet settled, and because no edge is negative, nothing found later can undercut it.
import heapqdef cheapest(start, goal, neighbors): # neighbors(node) -> [(next, cost)] best = {start: 0} heap = [(0, start)] while heap: cost, node = heapq.heappop(heap) if node == goal: return cost # the first pop of the goal is final if cost > best[node]: continue # stale entry: a cheaper one already won for nxt, w in neighbors(node): c = cost + w if c < best.get(nxt, float('inf')): best[nxt] = c heapq.heappush(heap, (c, nxt)) return -1 # goal unreachableTwo lines in that code carry the proof. The stale-entry check skips a heap entry once a cheaper copy of the same node has already been processed, which keeps the run at O(E log V) without a decrease-key operation. Returning early on the goal is safe only because costs never go negative. A bottleneck score, where a path is worth its weakest cell, fits the same code. Flip the heap to a max-heap, replace the sum with a min, and every pop is still final, since a path's minimum can only fall as it grows. When every step costs zero or one, drop the heap for a deque: push zero-cost moves to the front and one-cost moves to the back, and the deque stays sorted by cost on its own.
Asked at Uber
Three problems, from equal-cost hops to real weights. Bus Routes keeps BFS but searches over routes instead of stops. The safest path runs a multi-source BFS to price every cell, then a max-heap Dijkstra over those prices. Minimum Path Sum starts on the familiar DP and finishes on Dijkstra, with a 0-1 deque in the follow-up. Code each one in the editor and name its search before you open the walkthrough.
Bus Routes: BFS Over Routes
Problem
routes where routes[i] lists the stops bus i visits, looping through them forever. You begin at stop source on foot and want to reach stop target riding only buses. A transfer happens when you step off one bus at a stop and board another route that also serves it. Return the fewest buses you must board to get from source to target, or -1 if no sequence of buses gets you there.If
source equals target you are already there, so the answer is 0 even when no route serves that stop. The stops within one route are distinct, and two routes may share any number of stops.Input encoding. Each test case is a JSON array of three arguments:
routes (a list of integer lists, which may have different lengths), then source and target as integers. For example: [[[1,2,7],[3,6,7]], 1, 6].Board bus 0 at stop 1, ride to stop 7, transfer to bus 1, and ride to stop 6. That is two buses boarded.
Bus 0 reaches stop 6 directly after five stops. The route through stop 7 covers fewer stops but needs two buses, so the answer is 1.
Breadth-first search where each node is a whole route. A map from every stop to the routes that serve it supplies the neighbors, so one BFS level equals one more bus boarded and the first route that touches the target gives the answer.
Bus Routes: BFS Over Routes
Click "Run" to execute your code
Find the Safest Path in a Grid: Multi-Source BFS That Turns Into Dijkstra
Problem
n x n grid where each cell is 0 (empty) or 1 (a thief). You start at (0, 0) and want to reach (n - 1, n - 1), moving up, down, left, or right one cell at a time. Any cell may be stepped on, thieves included.A cell's safeness is its Manhattan distance to the nearest thief,
|r1 - r2| + |c1 - c2|. A path's safeness factor is the smallest safeness of any cell on it, both endpoints included. Return the largest safeness factor over all paths from (0, 0) to (n - 1, n - 1).The grid always holds at least one thief, and
1 <= n <= 400.Input encoding. The grid arrives as a JSON array of rows, each cell the number
0 or 1. For example: [[0,0,1],[0,0,0],[0,0,0]].Thieves sit on both the start and the finish, so every path touches a cell at distance 0.
Down the left column and along the bottom row visits safeness 2, 3, 4, 3, 2, so the weakest cell scores 2. The start itself scores 2, so no route beats it.
Two passes. A multi-source BFS seeded with every thief gives each cell its safeness, because the first wave to reach a cell came from its nearest thief. Then run Dijkstra with a max-heap where a path scores the minimum safeness along it; the first time the far corner leaves the heap, its score is final.
Find the Safest Path in a Grid: Multi-Source BFS That Turns Into Dijkstra
Click "Run" to execute your code
k, and you report whether the thief can reach the bank without entering a watched cell. One shared BFS breaks here, since a short-radius station can claim a cell first and stop a wider patrol from passing through it. Seed a max-heap with every station at its radius, spread outward losing one per step, and keep the largest leftover radius per cell. The coverage pass becomes Dijkstra, and a plain BFS over unwatched cells answers the question. The walkthrough runs both passes.Minimum Path Sum: From Grid DP to Dijkstra
Problem
m x n grid of non-negative integers. Read it as a city map where each value is the cost of driving into that block. Start at the top-left cell (0, 0) and finish at the bottom-right cell (m-1, n-1). From any cell you may move up, down, left, or right to a neighbor. A route's cost is the sum of every cell it enters, counting the start. Return the minimum route cost. An empty grid returns 0.The classic version allows only moves right and down. This one lifts that limit, and the row-by-row DP stops being correct.
Input encoding. Each test case is a JSON array of rows of integers, for example
[[1,3,1],[1,5,1],[4,2,1]]. The empty grid is [].Right, right, down, down: 1 + 3 + 1 + 1 + 1 = 7. On this grid the right-and-down route is already the cheapest.
Down, right, right, up to the top row, across it and down the last column. All ten blocks on that route cost 1. Every right-and-down route hits a 9, so the classic DP returns 16.
Use Dijkstra on a grid. Each block is a node, each move is an edge weighted by the block you enter, and a min-heap keyed on cost so far hands you the cheapest block reached next. The first time the bottom-right block comes off the heap, its cost is final.
Minimum Path Sum: From Grid DP to Dijkstra
Click "Run" to execute your code
Key Takeaways
- ✓Pick the search from the cost of one step. Equal costs take BFS, costs of zero or one take a deque, and any other non-negative cost takes Dijkstra with a min-heap.
- ✓In Bus Routes the node is a route and one hop is one bus, so index each stop to its routes once and let BFS walk routes through that map.
- ✓A path scored by its worst cell still runs on Dijkstra. Price the cells first with one multi-source BFS seeded from every thief, then pop the safest frontier from a max-heap.
- ✓Minimum Path Sum stays a DP only while moves go right and down. Four directions call for Dijkstra, and negative costs break Dijkstra, so ask whether a route may revisit a cell.
Citing this page?How we research these guides
Uber interview guideKnow what Uber asks before you walk in.
30 coding · 4 system design · 21 behavioral questions
Get their questions first.
InterviewLegend is independent and not affiliated with or endorsed by any company it covers.