|
| 1 | +# 329. Longest Increasing Path in a Matrix |
| 2 | + |
| 3 | +## Memo and DFS Solution |
| 4 | +- Run-time: O(V + E) |
| 5 | +- Space: O(V) |
| 6 | +- V = Vertices |
| 7 | +- E = Edges |
| 8 | + |
| 9 | +Simple solution is to perform a DFS for each element in the matrix. |
| 10 | +That would be a O(V + E)^2 run-time. |
| 11 | +We can further improve the run-time by using memoization to reduce the need to recalculate the same element over again. |
| 12 | +Therefore, each element in the matrix will only have one DFS performed on it. |
| 13 | +The memoization will keep the longest increasing path for each (i, j). |
| 14 | + |
| 15 | +Unlike a traditional DFS that uses a visited set, we can save more space by not using one here. |
| 16 | +As the question is worded, we only care about visiting elements that are increasing. |
| 17 | +Therefore, a cycle is not possible in this case, no need for a visited set. |
| 18 | + |
| 19 | +``` |
| 20 | +class Solution: |
| 21 | + def longestIncreasingPath(self, matrix: List[List[int]]) -> int: |
| 22 | +
|
| 23 | + def get_neighbors(r, c): |
| 24 | + dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] |
| 25 | + for _r, _c in dirs: |
| 26 | + _r += r |
| 27 | + _c += c |
| 28 | + if 0 <= _r < len(matrix) and 0 <= _c < len(matrix[0]): |
| 29 | + yield (_r, _c) |
| 30 | +
|
| 31 | + def dfs(i, j): |
| 32 | + if (i, j) in memo: |
| 33 | + return memo[(i, j)] |
| 34 | + longest = 1 |
| 35 | + for _i, _j in get_neighbors(i, j): |
| 36 | + if matrix[_i][_j] > matrix[i][j]: |
| 37 | + longest = max(longest, dfs(_i, _j) + 1) |
| 38 | + memo[(i , j)] = longest |
| 39 | + return longest |
| 40 | +
|
| 41 | + longest = 0 |
| 42 | + memo = dict() |
| 43 | + for i in range(len(matrix)): |
| 44 | + for j in range(len(matrix[0])): |
| 45 | + longest = max(longest, dfs(i, j)) |
| 46 | + return longest |
| 47 | +``` |
0 commit comments