Это является частью серии объяснений решения LeetCode ( index ). Если вам понравилось это решение или нашли его полезным, Пожалуйста, нравится Этот пост и/или upvote Мое решение по сообщению на форумах LeetCode Анкет
Проблема LeetCode #329 (жестко): самый длинный путь в матрице
Описание:
( прыгнуть в : Идея решения Код : JavaScript | Python | Java | C ++
Дал m x n
Целые числа Матрица
, вернуть длину самого длинного увеличения пути в Матрица
Анкет
Из каждой ячейки вы можете двигаться в четырех направлениях: слева, вправо, вверх или вниз. Ты не может Движение Диагонально или двигаться За пределами границы (т.е. обертывание не допускается).
Примеры:
Вход: | Матрица = [[9,9,4],[6,6,8],[2,1,1]] |
Выход: | 4 |
Объяснение: | Самый длинный увеличение пути – [1, 2, 6, 9]. |
Визуальный: |
Вход: | Матрица = [[3,4,5],[3,2,6],[2,2,1]] |
Выход: | 4 |
Объяснение: | Самый длинный увеличивающий путь – [3, 4, 5, 6]. Перемещение по диагонали не допускается. |
Визуальный: |
Вход: | Матрица = [[1]] |
Выход: | 1 |
Ограничения:
M.Length
n [i] .length
1, н
0 [i] [j]^31 - 1
Идея:
( Прыгните к : Описание задачи Код : JavaScript | Python | Java | C ++
Наивный подход здесь заключается в том, чтобы итерация через всю матрицу ( m ) и попытаться пройти по каждому ветвящему пути, но мы повторим одни и те же участки пути снова и снова.
Вместо того, чтобы повторять подзадачи, мы должны кэшировать эти завершенные результаты подзадачи для будущего использования в Мемуализация Структура данных ( memo ). Поскольку пути могут разветвляться в любом месте, мы также должны использовать Глубина-первый поиск ( dfs ) Подход с рекурсия эффективно пересечь пути.
( Примечание : Можно использовать снизу вверх Динамическое программирование ( dp ) Подход здесь также, но, поскольку нет удобного местоположения в нижней части фиксированной точки, мы должны были бы использовать Max-Heap Приоритетная очередь Чтобы пройти M в правильном восходящем порядке. Это подтолкнет Сложность времени к O (n * m * log (n * m)) , таким образом, код памяти более эффективен. )
Таким образом, мы можем просто итерации через каждую ячейку в M и запустите наш рекурсивный помощник ( dfs ), который заполняет значения в меморандум как он возвращается. Для данной ячейки, если решение этой ячейки уже найдено, мы можем возврат В противном случае мы получим лучший результат каждого из четырех возможных направлений пути.
Как только главная итерация завершится, самое высокое значение в меморандум будет нашим ответом. Итак, мы должны возврат Это.
Реализация:
Python может хорошо использовать @lru_cache Вместо необходимости создавать структуру данных вручную вручную.
Код JavaScript:
( Прыгните к : Описание задачи Идея решения
var longestIncreasingPath = function(M) { let ylen = M.length, xlen = M[0].length, ans = 0, memo = Array.from({length: ylen}, el => new Uint16Array(xlen)) const dfs = (y, x) => { if (memo[y][x]) return memo[y][x] let val = M[y][x] memo[y][x] = 1 + Math.max( y < ylen - 1 && M[y+1][x] < val ? dfs(y+1,x) : 0, y > 0 && M[y-1][x] < val ? dfs(y-1,x) : 0, x < xlen - 1 && M[y][x+1] < val ? dfs(y,x+1) : 0, x > 0 && M[y][x-1] < val ? dfs(y,x-1) : 0) return memo[y][x] } for (let i = 0; i < ylen; i++) for (let j = 0; j < xlen; j++) ans = Math.max(ans, dfs(i, j)) return ans };
Код Python:
( Прыгните к : Описание задачи Идея решения
class Solution: def longestIncreasingPath(self, M: List[List[int]]) -> int: ylen, xlen = len(M), len(M[0]) @lru_cache(maxsize=None) def dfs(y, x): val = M[y][x] return 1 + max( dfs(y+1,x) if y < ylen - 1 and val > M[y+1][x] else 0, dfs(y-1,x) if y > 0 and val > M[y-1][x] else 0, dfs(y,x+1) if x < xlen - 1 and val > M[y][x+1] else 0, dfs(y,x-1) if x > 0 and val > M[y][x-1] else 0) return max(dfs(y, x) for y in range(ylen) for x in range(xlen))
Код Java:
( Прыгните к : Описание задачи Идея решения
class Solution { public int longestIncreasingPath(int[][] M) { int ylen = M.length, xlen = M[0].length, ans = 0; int[][] memo = new int[ylen][xlen]; for (int i = 0; i < ylen; i++) for (int j = 0; j < xlen; j++) ans = Math.max(ans, dfs(i,j,M,memo)); return ans; } public int dfs(int y, int x, int[][] M, int[][] memo) { if (memo[y][x] > 0) return memo[y][x]; int val = M[y][x]; memo[y][x] = 1 + Math.max( Math.max(y < M.length - 1 && M[y+1][x] < val ? dfs(y+1,x,M,memo) : 0, y > 0 && M[y-1][x] < val ? dfs(y-1,x,M,memo) : 0), Math.max(x < M[0].length - 1 && M[y][x+1] < val ? dfs(y,x+1,M,memo) : 0, x > 0 && M[y][x-1] < val ? dfs(y,x-1,M,memo) : 0)); return memo[y][x]; } }
C ++ Код:
( Прыгните к : Описание задачи Идея решения
class Solution { public: int memo[200][200]; int longestIncreasingPath(vector>& M) { int ylen = M.size(), xlen = M[0].size(), ans = 0; for (int i = 0; i < ylen; i++) for (int j = 0; j < xlen; j++) ans = max(ans, dfs(i,j,M)); return ans; } int dfs(int y, int x, vector >& M) { if (memo[y][x]) return memo[y][x]; int val = M[y][x]; memo[y][x] = 1 + max( max(y < M.size() - 1 && M[y+1][x] < val ? dfs(y+1,x,M) : 0, y > 0 && M[y-1][x] < val ? dfs(y-1,x,M) : 0), max(x < M[0].size() - 1 && M[y][x+1] < val ? dfs(y,x+1,M) : 0, x > 0 && M[y][x-1] < val ? dfs(y,x-1,M) : 0)); return memo[y][x]; } };
Оригинал: “https://dev.to/seanpgallivan/solution-longest-increasing-path-in-a-matrix-4o5f”