Solving Leetcode Interviews in Seconds with AI: Unique Paths III
Introduction
In this blog post, we will explore how to solve the LeetCode problem "980" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.
Problem Statement
You are given an m x n integer array grid where grid[i][j] could be: 1 representing the starting square. There is exactly one starting square. 2 representing the ending square. There is exactly one ending square. 0 representing empty squares we can walk over. -1 representing obstacles that we cannot walk over. Return the number of 4-directional walks from the starting square to the ending square, that walk over every non-obstacle square exactly once. Example 1: Input: grid = [[1,0,0,0],[0,0,0,0],[0,0,2,-1]] Output: 2 Explanation: We have the following two paths: 1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2) 2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2) Example 2: Input: grid = [[1,0,0,0],[0,0,0,0],[0,0,0,2]] Output: 4 Explanation: We have the following four paths: 1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3) 2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3) 3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3) 4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3) Example 3: Input: grid = [[0,1],[2,0]] Output: 0 Explanation: There is no path that walks over every empty square exactly once. Note that the starting and ending square can be anywhere in the grid. Constraints: m == grid.length n == grid[i].length 1 <= m, n <= 20 1 <= m * n <= 20 -1 <= grid[i][j] <= 2 There is exactly one starting cell and one ending cell.
Explanation
Here's a breakdown of the solution approach, followed by the Python code:
- Depth-First Search (DFS): Explore all possible paths from the starting cell using DFS.
- Backtracking: If a path hits an obstacle, goes out of bounds, revisits a non-obstacle cell, or doesn't visit all non-obstacle cells exactly once before reaching the end, backtrack and try a different path.
Count Valid Paths: Increment the count only when a path successfully reaches the end cell after visiting all non-obstacle cells exactly once.
Runtime Complexity: O(4m*n), where m and n are the dimensions of the grid. In the worst case, we might explore all possible paths. Storage Complexity: O(m*n) due to the recursion depth of the DFS, corresponding to the stack space.
Code
def uniquePathsIII(grid):
"""
Finds the number of unique paths from the start to the end in a grid,
visiting every non-obstacle cell exactly once.
Args:
grid: A 2D list of integers representing the grid.
Returns:
The number of unique paths.
"""
rows = len(grid)
cols = len(grid[0])
start_row, start_col = -1, -1
empty_cells = 0
for i in range(rows):
for j in range(cols):
if grid[i][j] == 1:
start_row, start_col = i, j
elif grid[i][j] == 0:
empty_cells += 1
def dfs(row, col, visited_count):
"""
Performs Depth-First Search to find unique paths.
Args:
row: The current row index.
col: The current column index.
visited_count: The number of non-obstacle cells visited so far.
Returns:
The number of unique paths found from the current cell.
"""
if row < 0 or row >= rows or col < 0 or col >= cols or grid[row][col] == -1:
return 0
if grid[row][col] == 2:
if visited_count == empty_cells + 1: # +1 for the starting cell
return 1
else:
return 0
original_value = grid[row][col]
grid[row][col] = -1 # Mark as visited
paths = 0
paths += dfs(row + 1, col, visited_count + 1)
paths += dfs(row - 1, col, visited_count + 1)
paths += dfs(row, col + 1, visited_count + 1)
paths += dfs(row, col - 1, visited_count + 1)
grid[row][col] = original_value # Backtrack: unmark the cell
return paths
return dfs(start_row, start_col, 0)