Dijkstra algorithm for 2D array in Java
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
To run Dijkstra on a 2D array, treat each cell as a graph node and each allowed move to a neighbor as an edge with a non-negative cost. The algorithm then finds the minimum total path cost from a start cell to a target cell, which is useful for weighted grid navigation, routing, and puzzle solvers.
Model the Grid as a Graph
Suppose you have a grid where entering each cell has a cost:
You can move up, down, left, or right. Then:
- each cell is a vertex
- each legal move is an edge
- the path cost is the sum of visited-cell costs or move costs, depending on how you define the problem
In many grid problems, the distance to a neighbor is:
currentDistance + grid[nextRow][nextCol]
That keeps the implementation simple and intuitive.
Why Dijkstra Instead of BFS
BFS works only when every move has the same cost. Once different cells or edges have different non-negative weights, you need Dijkstra.
So:
- unweighted grid: BFS is enough
- weighted grid: use Dijkstra
If your weights can be negative, Dijkstra is not valid and you need a different algorithm.
Java Implementation
Here is a complete implementation for a weighted 2D grid.
This version includes the starting cell cost in the total distance. If your problem statement defines cost differently, adjust the initialization accordingly.
Why the Priority Queue Matters
Dijkstra repeatedly expands the node with the smallest known tentative distance. A priority queue makes that efficient.
The if (current.dist != dist[current.row][current.col]) check is also important. It skips stale queue entries that were inserted before a shorter path to the same cell was found.
Without that stale-entry guard, the code still may be correct, but it will do unnecessary work.
Obstacles and Blocked Cells
If some cells are impassable, represent them with a sentinel and skip them:
That keeps the graph model consistent. The blocked cell simply has no traversable incoming move in the algorithm.
Recovering the Actual Path
The example above returns only the minimum cost. If you also want the path, store a parent pointer for each cell:
- '
parentRow[row][col]' - '
parentCol[row][col]'
Whenever you relax a distance, record the current cell as the parent. After reaching the target, walk backward from the end cell to reconstruct the route.
That is the standard extension when the problem asks for both optimal cost and the actual sequence of moves.
Common Pitfalls
- Using BFS on a weighted grid and expecting correct shortest-path results. BFS only works when every move cost is equal.
- Forgetting that Dijkstra requires non-negative edge or cell costs.
- Omitting the stale-priority-queue-entry check, which can make the algorithm much slower on larger grids.
- Mishandling the definition of path cost, especially whether the start cell cost should be counted.
- Failing to bound-check neighbor coordinates before reading
grid[nr][nc].
Summary
- A 2D array can be treated as a graph where each cell is a node.
- Dijkstra is the right choice when movement costs are non-negative and not uniform.
- Use a priority queue plus a distance matrix to track the best known path to each cell.
- Add obstacle handling and parent tracking as needed for real pathfinding tasks.
- Be explicit about how you define cost, because that changes both initialization and the final answer.

