dp
2d-array
matrix power
]
Leetcode 0576. Out of Boundary Paths
Problem statement
https://leetcode.com/problems/out-of-boundary-paths/
Solution
Let dp(N, i, j) be number of solutions if we start from point (i, j) and we an make at most N steps. Then we need to consider the cases:
- If
i == morj == nori < 0orj < 0, it means that we reached boundary, so we return1: we found one more path. - If
N == 0, it means, that we out of moves, and we did not reached boundary yet, so we return0. - Finally, we try to make
4steps to all directions and return sum of all number of options. Note, that we visit this3-rd line only ifN >= 1, so when we call function with first argumentN-1,number of moves never be negative.
Complexity
We have O(m*n*N) states with 4 moves from each state, so we have time and space complexity O(m*n*N).
Code
class Solution:
def findPaths(self, m, n, N, i, j):
M = 10**9+7
@lru_cache(None)
def dfs(N, i, j):
if i == m or j == n or i < 0 or j < 0: return 1
if N == 0: return 0
return sum(dfs(N-1,i+x,j+y) for x,y in [[-1,0],[1,0],[0,-1],[0,1]])%M
return dfs(N,i,j)
Solution 2
This solution is inspired by this idea https://leetcode.com/problems/out-of-boundary-paths/discuss/341414/Possibility-of-O(m3n3logN)-solution. The idea is to reformulate problem as graph traversal problem, where we need to find number of paths. We have mn states in our grid and we create (m+2)*(n+2) x (m+2)*(n+2) adjacency matrix, where we add empty border.
Complexity
It is O(n^3*m^3*log(N)), because we need to evaluate power of matrix. Unfortunatelly it will give TLE in this problem, however I think it can be interesting to investigate this approach.
Code
import numpy as np
class Solution:
def findPaths(self, m, n, N, a, b):
def power(M, n, MOD):
result = np.eye(len(M), dtype = int)
while n > 0:
if n%2: result = np.dot(M, result) % MOD
M = np.dot(M, M) % MOD
n //= 2
return result
M, MOD = np.zeros(((m+2)*(n+2), (m+2)*(n+2)), dtype = int), 10**9+7
neibs = [[0,1],[0,-1],[1,0],[-1,0]]
for i in range(0, m+2):
for j in range(0, n+2):
if i == 0 or i == m+1 or j == 0 or j == n+1:
M[i*(n+2)+j][i*(n+2)+j] = 1
else:
for dx, dy in neibs:
M[i*(n+2)+j][(i+dx)*(n+2)+(j+dy)] = 1
S = power(M, N, MOD)
T = S[(a+1)*(n+2)+b+1]
return int(T.sum() - T.reshape(m+2, n+2)[1:m+1,1:n+1].sum()) % MOD