Check if There is a Valid Path in a Grid
MEDIUMDescription
You are given an m x n grid. Each cell of grid represents a street. The street of grid[i][j] can be:
1which means a street connecting the left cell and the right cell.2which means a street connecting the upper cell and the lower cell.3which means a street connecting the left cell and the lower cell.4which means a street connecting the right cell and the lower cell.5which means a street connecting the left cell and the upper cell.6which means a street connecting the right cell and the upper cell.
You will initially start at the street of the upper-left cell (0, 0). A valid path in the grid is a path that starts from the upper left cell (0, 0) and ends at the bottom-right cell (m - 1, n - 1). The path should only follow the streets.
Notice that you are not allowed to change any street.
Return true if there is a valid path in the grid or false otherwise.
Example 1:
Input: grid = [[2,4,3],[6,5,2]] Output: true Explanation: As shown you can start at cell (0, 0) and visit all the cells of the grid to reach (m - 1, n - 1).
Example 2:
Input: grid = [[1,2,1],[1,2,1]] Output: false Explanation: As shown you the street at cell (0, 0) is not connected with any street of any other cell and you will get stuck at cell (0, 0)
Example 3:
Input: grid = [[1,1,2]] Output: false Explanation: You will get stuck at cell (0, 1) and you cannot reach cell (0, 2).
Constraints:
m == grid.lengthn == grid[i].length1 <= m, n <= 3001 <= grid[i][j] <= 6
Approaches
Checkout 3 different approaches to solve Check if There is a Valid Path in a Grid. Click on different approaches to view the approach and algorithm in detail.
Recursive Depth-First Search (DFS)
This approach models the grid as a graph where each cell is a node. An edge exists between two adjacent cells if their respective streets connect to each other. The problem then becomes finding if a path exists from the source node (0, 0) to the destination node (m-1, n-1). DFS is a natural way to explore this path.
Algorithm
- We model the grid as a graph where each cell is a node. An edge exists between two adjacent cells if their respective streets connect to each other. The problem then becomes finding if a path exists from the source node (0, 0) to the destination node (m-1, n-1).
- We start a traversal from the cell (0, 0).
- We use a
visitedboolean grid to keep track of cells that are already part of the current exploration path to avoid cycles and redundant computations. - The core of the approach is a recursive function, say
dfs(row, col), which explores paths from the current cell(row, col). - Algorithm Steps:
- Define the possible moves for each street type. A street
kallows moves in two directions. We can store this in a 3D array, e.g.,moves[k-1] = {{dr1, dc1}, {dr2, dc2}}. - Create a recursive function
dfs(r, c, grid, visited). - Base Case: If
(r, c)is the destination(m-1, n-1), a path is found, returntrue. - Mark the current cell
(r, c)as visited. - Get the current street type
type = grid[r][c]. - Iterate through the two possible moves
(dr, dc)for thistype. - For each move, calculate the neighbor's coordinates
(nr, nc) = (r + dr, c + dc). - Validity Checks:
- Check if
(nr, nc)is within the grid boundaries. - Check if
(nr, nc)has been visited. - Crucially, check if the street at
(nr, nc)connects back to(r, c). This means one of the allowed moves from(nr, nc)must be(-dr, -dc).
- Check if
- If the move is valid, make a recursive call
dfs(nr, nc, grid, visited). If this call returnstrue, it means a path to the destination was found, so propagatetrueup the call stack. - The initial call is
dfs(0, 0, grid, visited).
- Define the possible moves for each street type. A street
class Solution {
// directions[street_type - 1] = {{dr1, dc1}, {dr2, dc2}}
private int[][][] directions = {
{{0, -1}, {0, 1}}, // 1: left-right
{{-1, 0}, {1, 0}}, // 2: up-down
{{0, -1}, {1, 0}}, // 3: left-down
{{0, 1}, {1, 0}}, // 4: right-down
{{0, -1}, {-1, 0}}, // 5: left-up
{{0, 1}, {-1, 0}} // 6: right-up
};
private int m, n;
private boolean[][] visited;
public boolean hasValidPath(int[][] grid) {
m = grid.length;
n = grid[0].length;
visited = new boolean[m][n];
return dfs(0, 0, grid);
}
private boolean dfs(int r, int c, int[][] grid) {
if (r == m - 1 && c == n - 1) {
return true;
}
visited[r][c] = true;
int streetType = grid[r][c];
for (int[] dir : directions[streetType - 1]) {
int nr = r + dir[0];
int nc = c + dir[1];
if (nr >= 0 && nr < m && nc >= 0 && nc < n && !visited[nr][nc]) {
// Check if the next street connects back
int nextStreetType = grid[nr][nc];
for (int[] backDir : directions[nextStreetType - 1]) {
if (nr + backDir[0] == r && nc + backDir[1] == c) {
if (dfs(nr, nc, grid)) {
return true;
}
}
}
}
}
return false;
}
}
Complexity Analysis
Pros and Cons
- Conceptually straightforward and easy to implement.
- Follows the problem's path-finding nature directly.
- Can lead to a
StackOverflowErrorfor very large grids where the path is long and winding, as the recursion depth could exceed the stack limit.
Code Solutions
Checking out 3 solutions in different languages for Check if There is a Valid Path in a Grid. Click on different languages to view the code.
Video Solution
Watch the video walkthrough for Check if There is a Valid Path in a Grid
Similar Questions
5 related questions you might find useful
Algorithms:
Data Structures:
Companies:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.