Intuition
Each cell type connects exactly two of the four neighbours. From (0, 0), do a DFS that walks onto a neighbouring cell only when both sides agree their streets connect.
Explanation
Approach
- For each street type, list its two outgoing directions (e.g. type 1 connects left + right).
- Run DFS from
(0, 0): for each direction allowed by the current cell, step to the neighbour and check that the neighbour's street also points back; if yes and not visited, recurse. - Return
Trueif(m - 1, n - 1)is ever reached.
Complexity
- Time:
O(m · n)— each cell visited at most once. - Space:
O(m · n)— visited matrix and recursion stack.
Implementation
class Solution {
private static final int[][][] streets = {
{},
{{0, -1}, {0, 1}},
{{-1, 0}, {1, 0}},
{{0, -1}, {1, 0}},
{{0, 1}, {1, 0}},
{{0, -1}, {-1, 0}},
{{0, 1}, {-1, 0}}
};
public boolean hasValidPath(int[][] grid) {
int m = grid.length, n = grid[0].length;
boolean[][] visited = new boolean[m][n];
return dfs(grid, visited, 0, 0, m, n);
}
private boolean dfs(int[][] grid, boolean[][] visited, int r, int c, int m, int n) {
if (r == m - 1 && c == n - 1) return true;
visited[r][c] = true;
for (int[] dir : streets[grid[r][c]]) {
int nr = r + dir[0], nc = c + dir[1];
if (nr < 0 || nr >= m || nc < 0 || nc >= n || visited[nr][nc]) continue;
boolean connects = false;
for (int[] ndir : streets[grid[nr][nc]]) {
if (ndir[0] == -dir[0] && ndir[1] == -dir[1]) {
connects = true;
break;
}
}
if (connects && dfs(grid, visited, nr, nc, m, n)) return true;
}
return false;
}
}