Рубрики
Без рубрики

Решение: самый длинный увеличение пути в матрице

Это является частью серии объяснений решений LeetCode (индекс). Если вам понравилось это решение или fou … с меткой алгоритмы, JavaScript, Java, Python.

Это является частью серии объяснений решения 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”