980. Unique Paths III
Problem
On a 2-dimensional grid
, there are 4 types of squares:
1
represents the starting square. There is exactly one starting square.2
represents the ending square. There is exactly one ending square.0
represents empty squares we can walk over.-1
represents 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: [[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: [[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: [[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.
Note:
1 <= grid.length * grid[0].length <= 20
Discussion
This problem requires us to find all unique paths from point 1
to 2
.
As this requires iterations through all elements and all paths between two points, we may come up with the idea of using DFS. Things become straight forward now as actually this problem is very similar to 79. Word Search, which is obvious a DFS and back-tracking problem.
Besides DFS and back-tracking to find all unique paths, we also have to make
sure all 0
is being used exactly once in the paths, and no other values
besides 0
and 1
are used. Achieving this we simply count all the 0
in grid
and do validation.
Solution
We begin our solution with a loop finding all the 0
in the grid, and scanning
1
to begin our DFS method. We use DFS by recursion here for simplicity.
In the DFS, we temporary update the visited node to some special value (999
)
to prevent re-use of the same element in the grid and we restore the value after
each iteration.
Besides we maintain a variable step
to see how many 0
or 1
is visited.
When we reach 2
, we check the value of step
to see if all 0
are being passed through exactly once. Then we update our result number if
a new unique path is founded.
from typing import List
class Solution:
def uniquePathsIII(self, grid: List[List[int]]) -> int:
self.grid = grid
self.result = 0
self.number_of_zero = 0
for i in range(len(grid)):
for j in range(len(grid[i])):
if grid[i][j] == 0:
self.number_of_zero += 1
for i in range(len(grid)):
for j in range(len(grid[i])):
if grid[i][j] == 1:
self.dfs(i, j, 0)
return self.result
def dfs(self, i, j, step):
if self.grid[i][j] == 2:
if step == self.number_of_zero + 1:
self.result += 1
return
if self.grid[i][j] in (0, 1):
temp, self.grid[i][j] = self.grid[i][j], 999
if i > 0:
self.dfs(i - 1, j, step + 1)
if j > 0:
self.dfs(i, j - 1, step + 1)
if i < len(self.grid) - 1:
self.dfs(i + 1, j, step + 1)
if j < len(self.grid[0]) - 1:
self.dfs(i, j + 1, step + 1)
self.grid[i][j] = temp
return
Complexity Analysis
- Time Complexity:
O(3^n)
, as although we have 4 directions go search in each iteration, we have at most 3 directions to go in each iteration. - Space Complexity:
O(n)
, as we apply recursion which at most holdingn
layer of instances. Besides only the input grid and other constant variables are maintained in memory.