2617. Minimum Number of Visited Cells in a Grid
Problem Description
You have an m x n
integer matrix called grid
, and you start at the top-left cell (0, 0)
. Your goal is to reach the bottom-right cell (m-1, n-1)
with the minimum number of cell visits.
From any cell (i, j)
, you can only move in two ways:
- Move right: Jump to any cell
(i, k)
wherej < k <= grid[i][j] + j
. This means you can jump rightward to any cell within a range determined by the current cell's value. - Move down: Jump to any cell
(k, j)
wherei < k <= grid[i][j] + i
. This means you can jump downward to any cell within a range determined by the current cell's value.
The value grid[i][j]
determines how far you can jump from that cell. For example, if you're at cell (2, 3)
and grid[2][3] = 4
, you can:
- Jump right to any cell
(2, k)
where3 < k <= 7
(since4 + 3 = 7
) - Jump down to any cell
(k, 3)
where2 < k <= 6
(since4 + 2 = 6
)
The problem asks you to find the minimum number of cells you need to visit (including the starting and ending cells) to reach from (0, 0)
to (m-1, n-1)
. If it's impossible to reach the destination, return -1
.
The solution uses a dynamic programming approach with priority queues. It maintains a dist
matrix where dist[i][j]
represents the minimum number of cells visited to reach cell (i, j)
from the start. For each row and column, it uses min-heaps to efficiently find the closest reachable cell that can jump to the current position. The algorithm processes cells in order, updating distances when a shorter path is found through either horizontal or vertical jumps.
Flowchart Walkthrough
First, let's pin down the algorithm using the Flowchart. Here's a step-by-step walkthrough:
Is it a graph?
- Yes: This problem can be modeled as a graph where each cell
(i, j)
is a node, and there are directed edges from each cell to all cells it can jump to (rightward or downward based ongrid[i][j]
value).
Is it a tree?
- No: The graph is not a tree because there can be multiple paths to reach the same cell, and cycles might exist.
Is the problem related to directed acyclic graphs?
- No: While the graph is directed, it's not necessarily acyclic. The problem doesn't involve topological ordering.
Is the problem related to shortest paths?
- Yes: We need to find the minimum number of cells to visit from
(0, 0)
to(m-1, n-1)
, which is essentially finding the shortest path in terms of number of hops.
Is the graph Weighted?
- No: Each move from one cell to another has the same cost (1 cell visit). All edges have uniform weight.
BFS
- Yes: Since we're looking for the shortest path in an unweighted graph, BFS is the appropriate algorithm.
Conclusion: The flowchart suggests using BFS (Breadth-First Search) for finding the minimum number of cells to visit. The solution implements a variation of BFS using priority queues to efficiently handle the dynamic jumps. Each cell can jump to multiple cells within a range, and BFS explores cells level by level, ensuring the first time we reach the destination gives us the shortest path.
Intuition
When we think about finding the minimum number of cells to visit, we're essentially looking for the shortest path from start to finish. The key insight is that this is a graph problem where each cell can "jump" to multiple other cells based on its value.
The standard BFS approach would work, but there's a catch - from each cell (i, j)
, we might be able to jump to many cells (potentially up to grid[i][j]
cells in each direction). If we naively add all reachable cells to our BFS queue, we could end up with a lot of redundant work.
Here's where the clever optimization comes in: instead of thinking "from this cell, where can I go?", we flip the perspective to "to reach this cell, where could I have come from?". This reverse thinking leads us to maintain priority queues for each row and column.
For any cell (i, j)
we're trying to reach:
- It could be reached from any cell in the same row to its left (cells
(i, j')
wherej' < j
) - It could be reached from any cell in the same column above it (cells
(i', j)
wherei' < i
)
But not all cells to the left or above can actually reach (i, j)
. A cell (i, j')
can only reach (i, j)
if grid[i][j'] + j' >= j
. Similarly for cells above.
The priority queue optimization works because:
- We process cells in order (row by row, column by column)
- For each row
i
, we maintain a min-heap of cells that could potentially jump to future cells in that row - As we move right in a row, some cells become "expired" - they can no longer reach the current position, so we remove them
- The cell with minimum distance that can still reach our current position is always at the top of the heap
This transforms what could be an expensive operation (checking all possible source cells) into an efficient one using heaps. The dist[i][j]
tracks the minimum cells visited to reach (i, j)
, and we update it based on the best option from either the row heap or column heap.
Learn more about Stack, Breadth-First Search, Union Find, Dynamic Programming, Monotonic Stack and Heap (Priority Queue) patterns.
Solution Approach
Let's denote the number of rows of the grid as m
and the number of columns as n
. We define dist[i][j]
to be the shortest distance from the coordinate (0, 0)
to the coordinate (i, j)
. Initially, dist[0][0] = 1
(starting cell counts as 1 visit) and dist[i][j] = -1
for all other positions (unreachable by default).
The key idea is to maintain priority queues (min-heaps) for efficient lookups:
row[i]
: A min-heap for rowi
containing pairs(dist[i][j], j)
representing cells in that row that could potentially jump to cells further rightcol[j]
: A min-heap for columnj
containing pairs(dist[i][j], i)
representing cells in that column that could potentially jump to cells further down
The algorithm processes cells in row-major order (left to right, top to bottom):
-
For each cell
(i, j)
: -
Check horizontal jumps (from left cells in the same row):
- Clean up expired entries: Remove cells from
row[i]
heap that can't reach positionj
(wheregrid[i][j'] + j' < j
) - If valid cells remain in the heap, the top element gives the minimum distance to reach
(i, j)
from the left - Update
dist[i][j] = row[i][0][0] + 1
if this gives a better path
- Clean up expired entries: Remove cells from
-
Check vertical jumps (from upper cells in the same column):
- Clean up expired entries: Remove cells from
col[j]
heap that can't reach positioni
(wheregrid[i'][j] + i' < i
) - If valid cells remain in the heap, the top element gives the minimum distance to reach
(i, j)
from above - Update
dist[i][j] = col[j][0][0] + 1
if this gives a better path
- Clean up expired entries: Remove cells from
-
Add current cell to heaps:
- If
dist[i][j] != -1
(cell is reachable), add(dist[i][j], j)
torow[i]
and(dist[i][j], i)
tocol[j]
- These entries will be considered for future cells that might be reachable from
(i, j)
- If
The algorithm efficiently maintains the invariant that the top of each heap contains the cell with minimum distance that can still reach future positions. By processing cells in order and using heaps to track the best sources, we avoid redundant checks while ensuring we find the optimal path.
Finally, dist[m-1][n-1]
gives us the minimum number of cells to visit to reach the bottom-right corner, or -1
if it's unreachable.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example to illustrate the solution approach.
Consider a 3×3 grid:
grid = [[2, 1, 2], [1, 1, 1], [1, 1, 1]]
We want to find the minimum cells to visit from (0,0) to (2,2).
Initial Setup:
dist
matrix initialized with -1 everywhere exceptdist[0][0] = 1
row[0], row[1], row[2]
are empty min-heaps for each rowcol[0], col[1], col[2]
are empty min-heaps for each column
Processing (0,0):
- Current cell value:
grid[0][0] = 2
- No cells to the left or above, so
dist[0][0]
remains 1 - Add to heaps:
row[0].push((1, 0))
andcol[0].push((1, 0))
- From (0,0), we can jump right to (0,1) or (0,2), or down to (1,0) or (2,0)
Processing (0,1):
- Check row[0] heap: Contains (1, 0). Since
grid[0][0] + 0 = 2 + 0 = 2 >= 1
, cell (0,0) can reach (0,1) - Update:
dist[0][1] = 1 + 1 = 2
- Add to heaps:
row[0].push((2, 1))
andcol[1].push((2, 0))
Processing (0,2):
- Check row[0] heap: Top is (1, 0). Since
grid[0][0] + 0 = 2 >= 2
, (0,0) can reach (0,2) - Update:
dist[0][2] = 1 + 1 = 2
- Add to heaps:
row[0].push((2, 2))
andcol[2].push((2, 0))
Processing (1,0):
- Check col[0] heap: Contains (1, 0). Since
grid[0][0] + 0 = 2 >= 1
, cell (0,0) can reach (1,0) - Update:
dist[1][0] = 1 + 1 = 2
- Add to heaps:
row[1].push((2, 0))
andcol[0].push((2, 1))
Processing (1,1):
- Check row[1] heap: Contains (2, 0). Since
grid[1][0] + 0 = 1 + 0 = 1 >= 1
, cell (1,0) can reach (1,1) - Check col[1] heap: Contains (2, 0). Since
grid[0][1] + 0 = 1 + 0 = 1 >= 1
, cell (0,1) can reach (1,1) - Both give distance 3, so
dist[1][1] = 3
- Add to heaps accordingly
Processing (1,2):
- Check row[1] heap: Best valid source gives distance 3
- Check col[2] heap: Contains (2, 0). Since
grid[0][2] + 0 = 2 >= 1
, gives distance 3 - Update:
dist[1][2] = 3
Processing (2,0):
- Check col[0] heap: Multiple entries, but (1, 0) with
grid[0][0] + 0 = 2 >= 2
can reach (2,0) - Update:
dist[2][0] = 2
Processing (2,1):
- Check row[2] heap: Contains (2, 0). Since
grid[2][0] + 0 = 1 >= 1
, gives distance 3 - Check col[1] heap: Best valid source also gives distance 3
- Update:
dist[2][1] = 3
Processing (2,2):
- Check row[2] heap: Best valid source from (2,0) or (2,1)
- Check col[2] heap: Best valid source from (0,2) or (1,2)
- Minimum distance found:
dist[2][2] = 3
Result: The minimum number of cells to visit is 3. One optimal path is (0,0) → (0,2) → (2,2).
The key insight is how the heaps efficiently track which cells can reach the current position, avoiding the need to check all previous cells in the row/column. The heap cleanup step removes cells that are too far away to make the jump, ensuring we only consider valid sources.
Solution Implementation
1from typing import List
2from heapq import heappush, heappop
3
4class Solution:
5 def minimumVisitedCells(self, grid: List[List[int]]) -> int:
6 # Get grid dimensions
7 rows, cols = len(grid), len(grid[0])
8
9 # Initialize distance matrix with -1 (unreachable)
10 distances = [[-1] * cols for _ in range(rows)]
11 # Starting cell has distance 1
12 distances[0][0] = 1
13
14 # Priority queues for each row and column
15 # Each heap stores tuples of (distance, position)
16 row_heaps = [[] for _ in range(rows)]
17 col_heaps = [[] for _ in range(cols)]
18
19 # Process each cell in row-major order
20 for row in range(rows):
21 for col in range(cols):
22 # Clean up row heap: remove cells that can't reach current position
23 # A cell at position (row, prev_col) can reach up to prev_col + grid[row][prev_col]
24 while row_heaps[row] and grid[row][row_heaps[row][0][1]] + row_heaps[row][0][1] < col:
25 heappop(row_heaps[row])
26
27 # Update distance from leftward cells in same row
28 if row_heaps[row]:
29 min_distance_from_row = row_heaps[row][0][0] + 1
30 if distances[row][col] == -1 or distances[row][col] > min_distance_from_row:
31 distances[row][col] = min_distance_from_row
32
33 # Clean up column heap: remove cells that can't reach current position
34 # A cell at position (prev_row, col) can reach up to prev_row + grid[prev_row][col]
35 while col_heaps[col] and grid[col_heaps[col][0][1]][col] + col_heaps[col][0][1] < row:
36 heappop(col_heaps[col])
37
38 # Update distance from upward cells in same column
39 if col_heaps[col]:
40 min_distance_from_col = col_heaps[col][0][0] + 1
41 if distances[row][col] == -1 or distances[row][col] > min_distance_from_col:
42 distances[row][col] = min_distance_from_col
43
44 # If current cell is reachable, add it to corresponding heaps
45 # so it can be used to reach other cells
46 if distances[row][col] != -1:
47 heappush(row_heaps[row], (distances[row][col], col))
48 heappush(col_heaps[col], (distances[row][col], row))
49
50 # Return the distance to bottom-right cell
51 return distances[-1][-1]
52
1class Solution {
2 public int minimumVisitedCells(int[][] grid) {
3 int rows = grid.length;
4 int cols = grid[0].length;
5
6 // Distance array to store minimum steps to reach each cell
7 int[][] distance = new int[rows][cols];
8
9 // Priority queues for each row to maintain cells reachable from left
10 // Each element: [distance to reach, column index]
11 PriorityQueue<int[]>[] rowQueues = new PriorityQueue[rows];
12
13 // Priority queues for each column to maintain cells reachable from top
14 // Each element: [distance to reach, row index]
15 PriorityQueue<int[]>[] colQueues = new PriorityQueue[cols];
16
17 // Initialize distance array with -1 (unreachable) and create priority queues
18 for (int i = 0; i < rows; i++) {
19 Arrays.fill(distance[i], -1);
20 // Sort by distance first, then by position if distances are equal
21 rowQueues[i] = new PriorityQueue<>((a, b) ->
22 a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
23 }
24
25 // Initialize column priority queues with same comparator
26 for (int j = 0; j < cols; j++) {
27 colQueues[j] = new PriorityQueue<>((a, b) ->
28 a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
29 }
30
31 // Starting position requires 1 step (counting itself)
32 distance[0][0] = 1;
33
34 // Process each cell in row-major order
35 for (int i = 0; i < rows; i++) {
36 for (int j = 0; j < cols; j++) {
37
38 // Process row queue: remove cells that cannot reach current position
39 while (!rowQueues[i].isEmpty()) {
40 int[] top = rowQueues[i].peek();
41 int sourceCol = top[1];
42 int maxReach = sourceCol + grid[i][sourceCol];
43
44 // If this cell cannot reach position (i, j), remove it
45 if (maxReach < j) {
46 rowQueues[i].poll();
47 } else {
48 break;
49 }
50 }
51
52 // Update distance from left (same row)
53 if (!rowQueues[i].isEmpty()) {
54 int minSteps = rowQueues[i].peek()[0] + 1;
55 if (distance[i][j] == -1 || minSteps < distance[i][j]) {
56 distance[i][j] = minSteps;
57 }
58 }
59
60 // Process column queue: remove cells that cannot reach current position
61 while (!colQueues[j].isEmpty()) {
62 int[] top = colQueues[j].peek();
63 int sourceRow = top[1];
64 int maxReach = sourceRow + grid[sourceRow][j];
65
66 // If this cell cannot reach position (i, j), remove it
67 if (maxReach < i) {
68 colQueues[j].poll();
69 } else {
70 break;
71 }
72 }
73
74 // Update distance from top (same column)
75 if (!colQueues[j].isEmpty()) {
76 int minSteps = colQueues[j].peek()[0] + 1;
77 if (distance[i][j] == -1 || minSteps < distance[i][j]) {
78 distance[i][j] = minSteps;
79 }
80 }
81
82 // If current cell is reachable, add it to queues for future cells
83 if (distance[i][j] != -1) {
84 rowQueues[i].offer(new int[] {distance[i][j], j});
85 colQueues[j].offer(new int[] {distance[i][j], i});
86 }
87 }
88 }
89
90 // Return minimum steps to reach bottom-right corner
91 return distance[rows - 1][cols - 1];
92 }
93}
94
1class Solution {
2public:
3 int minimumVisitedCells(vector<vector<int>>& grid) {
4 int rows = grid.size();
5 int cols = grid[0].size();
6
7 // Distance matrix to store minimum steps to reach each cell
8 // -1 indicates unreachable
9 vector<vector<int>> distance(rows, vector<int>(cols, -1));
10
11 // Min heaps for each row and column to track reachable cells
12 // Each element is (distance, column_index) for row heaps
13 // Each element is (distance, row_index) for column heaps
14 using PairIntInt = pair<int, int>;
15 priority_queue<PairIntInt, vector<PairIntInt>, greater<PairIntInt>> rowHeaps[rows];
16 priority_queue<PairIntInt, vector<PairIntInt>, greater<PairIntInt>> colHeaps[cols];
17
18 // Starting position requires 1 step (counting the starting cell itself)
19 distance[0][0] = 1;
20
21 // Process each cell in row-major order
22 for (int row = 0; row < rows; ++row) {
23 for (int col = 0; col < cols; ++col) {
24 // Remove cells from row heap that can't reach current position
25 // A cell at column 'prevCol' can reach current column if:
26 // grid[row][prevCol] + prevCol >= col
27 while (!rowHeaps[row].empty() &&
28 grid[row][rowHeaps[row].top().second] + rowHeaps[row].top().second < col) {
29 rowHeaps[row].pop();
30 }
31
32 // Update distance if we can reach this cell from same row
33 if (!rowHeaps[row].empty()) {
34 int newDistance = rowHeaps[row].top().first + 1;
35 if (distance[row][col] == -1 || newDistance < distance[row][col]) {
36 distance[row][col] = newDistance;
37 }
38 }
39
40 // Remove cells from column heap that can't reach current position
41 // A cell at row 'prevRow' can reach current row if:
42 // grid[prevRow][col] + prevRow >= row
43 while (!colHeaps[col].empty() &&
44 grid[colHeaps[col].top().second][col] + colHeaps[col].top().second < row) {
45 colHeaps[col].pop();
46 }
47
48 // Update distance if we can reach this cell from same column
49 if (!colHeaps[col].empty()) {
50 int newDistance = colHeaps[col].top().first + 1;
51 if (distance[row][col] == -1 || newDistance < distance[row][col]) {
52 distance[row][col] = newDistance;
53 }
54 }
55
56 // If current cell is reachable, add it to heaps for future cells
57 if (distance[row][col] != -1) {
58 rowHeaps[row].emplace(distance[row][col], col);
59 colHeaps[col].emplace(distance[row][col], row);
60 }
61 }
62 }
63
64 // Return minimum steps to reach bottom-right corner
65 return distance[rows - 1][cols - 1];
66 }
67};
68
1function minimumVisitedCells(grid: number[][]): number {
2 const rows = grid.length;
3 const cols = grid[0].length;
4
5 // Distance matrix to store minimum steps to reach each cell
6 // -1 indicates unreachable
7 const distance: number[][] = Array(rows).fill(null).map(() => Array(cols).fill(-1));
8
9 // Min heaps for each row and column to track reachable cells
10 // Each element is [distance, columnIndex] for row heaps
11 // Each element is [distance, rowIndex] for column heaps
12 const rowHeaps: Array<Array<[number, number]>> = Array(rows).fill(null).map(() => []);
13 const colHeaps: Array<Array<[number, number]>> = Array(cols).fill(null).map(() => []);
14
15 // Helper function to maintain min heap property when pushing
16 const heapPush = (heap: Array<[number, number]>, item: [number, number]): void => {
17 heap.push(item);
18 heap.sort((a, b) => a[0] - b[0]);
19 };
20
21 // Helper function to pop minimum element from heap
22 const heapPop = (heap: Array<[number, number]>): [number, number] | undefined => {
23 return heap.shift();
24 };
25
26 // Helper function to peek at minimum element without removing
27 const heapPeek = (heap: Array<[number, number]>): [number, number] | undefined => {
28 return heap[0];
29 };
30
31 // Starting position requires 1 step (counting the starting cell itself)
32 distance[0][0] = 1;
33
34 // Process each cell in row-major order
35 for (let row = 0; row < rows; row++) {
36 for (let col = 0; col < cols; col++) {
37 // Remove cells from row heap that can't reach current position
38 // A cell at column 'prevCol' can reach current column if:
39 // grid[row][prevCol] + prevCol >= col
40 while (rowHeaps[row].length > 0) {
41 const top = heapPeek(rowHeaps[row]);
42 if (top && grid[row][top[1]] + top[1] < col) {
43 heapPop(rowHeaps[row]);
44 } else {
45 break;
46 }
47 }
48
49 // Update distance if we can reach this cell from same row
50 if (rowHeaps[row].length > 0) {
51 const top = heapPeek(rowHeaps[row]);
52 if (top) {
53 const newDistance = top[0] + 1;
54 if (distance[row][col] === -1 || newDistance < distance[row][col]) {
55 distance[row][col] = newDistance;
56 }
57 }
58 }
59
60 // Remove cells from column heap that can't reach current position
61 // A cell at row 'prevRow' can reach current row if:
62 // grid[prevRow][col] + prevRow >= row
63 while (colHeaps[col].length > 0) {
64 const top = heapPeek(colHeaps[col]);
65 if (top && grid[top[1]][col] + top[1] < row) {
66 heapPop(colHeaps[col]);
67 } else {
68 break;
69 }
70 }
71
72 // Update distance if we can reach this cell from same column
73 if (colHeaps[col].length > 0) {
74 const top = heapPeek(colHeaps[col]);
75 if (top) {
76 const newDistance = top[0] + 1;
77 if (distance[row][col] === -1 || newDistance < distance[row][col]) {
78 distance[row][col] = newDistance;
79 }
80 }
81 }
82
83 // If current cell is reachable, add it to heaps for future cells
84 if (distance[row][col] !== -1) {
85 heapPush(rowHeaps[row], [distance[row][col], col]);
86 heapPush(colHeaps[col], [distance[row][col], row]);
87 }
88 }
89 }
90
91 // Return minimum steps to reach bottom-right corner
92 return distance[rows - 1][cols - 1];
93}
94
Time and Space Complexity
Time Complexity: O(m × n × log(m × n))
The algorithm iterates through each cell of the m × n
grid exactly once. For each cell (i, j)
:
- We perform while loops to clean up outdated entries from the heaps, but each element is removed at most once across all iterations
- We perform at most 2 heap push operations (one for
row[i]
and one forcol[j]
) - We perform at most 2 heap pop operations during the cleanup phase
Since each cell can be pushed to heaps at most twice (once in its row heap and once in its column heap), the total number of heap operations is O(m × n)
. Each heap operation (push/pop) takes O(log k)
time where k
is the heap size. In the worst case, a single row or column heap could contain up to O(m × n)
elements (though more typically it would be O(n)
for row heaps and O(m)
for column heaps).
Therefore, the overall time complexity is O(m × n × log(m × n))
.
Space Complexity: O(m × n)
The space usage includes:
dist
array:O(m × n)
to store distances for each cellrow
array:m
heaps that collectively can store up toO(m × n)
elements in totalcol
array:n
heaps that collectively can store up toO(m × n)
elements in total
While the heaps could theoretically store duplicate entries for cells, the total space across all heaps is bounded by O(m × n)
since each cell contributes at most a constant number of entries.
Therefore, the overall space complexity is O(m × n)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Heap Cleanup Condition
One of the most common mistakes is getting the cleanup condition wrong when removing expired entries from the heaps. The condition needs to check whether a cell can still reach the current position.
Incorrect Implementation:
# Wrong: Using <= instead of < while row_heaps[row] and grid[row][row_heaps[row][0][1]] + row_heaps[row][0][1] <= col: heappop(row_heaps[row])
Why it's wrong: If a cell at position j'
has grid[row][j'] + j' = col
, it means the cell can exactly reach position col
(since we can jump to any position in range (j', grid[row][j'] + j']
). Using <=
would incorrectly remove this valid cell.
Correct Implementation:
# Correct: A cell at j' can reach col if j' < col <= grid[row][j'] + j' while row_heaps[row] and grid[row][row_heaps[row][0][1]] + row_heaps[row][0][1] < col: heappop(row_heaps[row])
2. Forgetting to Initialize Starting Cell Distance
Another pitfall is forgetting to set distances[0][0] = 1
or incorrectly setting it to 0.
Incorrect:
distances = [[-1] * cols for _ in range(rows)]
# Forgot to set distances[0][0] = 1
Why it's wrong: The problem counts the number of cells visited, including the starting cell. Without initializing the starting cell's distance, the algorithm won't propagate any distances, and all cells will remain unreachable.
3. Heap Entry Order Confusion
Mixing up what to store in the heap entries can lead to incorrect results.
Incorrect:
# Wrong: Storing (position, distance) instead of (distance, position) heappush(row_heaps[row], (col, distances[row][col])) heappush(col_heaps[col], (row, distances[row][col]))
Why it's wrong: Min-heaps in Python compare tuples element by element. We want to prioritize by minimum distance first, so distance must be the first element. Putting position first would prioritize by position instead of distance.
Correct Implementation:
# Correct: (distance, position) ensures we get minimum distance first heappush(row_heaps[row], (distances[row][col], col)) heappush(col_heaps[col], (distances[row][col], row))
4. Not Checking if Cell is Reachable Before Adding to Heaps
Adding unreachable cells (with distance -1) to the heaps will cause incorrect propagation.
Incorrect:
# Wrong: Adding cell to heaps without checking if it's reachable heappush(row_heaps[row], (distances[row][col], col)) heappush(col_heaps[col], (distances[row][col], row))
Correct Implementation:
# Only add reachable cells to the heaps if distances[row][col] != -1: heappush(row_heaps[row], (distances[row][col], col)) heappush(col_heaps[col], (distances[row][col], row))
Which data structure is used in a depth first search?
Recommended Readings
Stack Intro Imagine you have a pile of books on your desk If you want to add a new book you place it on top If you want to read a book you take it from the top And if you simply want to see which book is on the top you
https assets algo monster cover_photos bfs svg Breadth First Search on Trees Hopefully by this time you've drunk enough DFS Kool Aid to understand its immense power and seen enough visualization to create a call stack in your mind Now let me introduce the companion spell Breadth First Search BFS
Union Find Disjoint Set Union Data Structure Introduction Prerequisite Depth First Search Review problems dfs_intro Once we have a strong grasp of recursion and Depth First Search we can now introduce Disjoint Set Union DSU This data structure is motivated by the following problem Suppose we have sets of elements
Want a Structured Path to Master System Design Too? Don’t Miss This!