Leetcode - Longest Increasing Path in a Matrix

Question - post

Given an integer matrix, find the length of the longest increasing path.

From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).

Example 1:

nums = [[9,9,4],
         ^
        [6,6,8],
         ^
        [2,1,1]]
         ^ ^

Return 4 The longest increasing path is [1, 2, 6, 9].

Example 2:

nums = [[3,4,5],
         ^ ^ ^
        [3,2,6],
             ^
        [2,2,1]]

Return 4 The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.


Solution - code

The strategy is to do Path Finding algorithms (DFS, BFS, …) to every element. In order to make the path-finding process faster, you could apply the memorization technique from Dynamic Programming to it.

For example:

[[9,9,4],
 [6,6,8],
 [2,1,1]]

Graph of going through the possible paths:

...

We can directly use the outcome from the previous visited paths. e.g: The 6->9 path was visited when searching the 2->6->... path. That’s why we need to memorize the visited paths.

Eventually, the problem is a composite problem of Path Finding and Dynamic Programming.

class Solution(object):
    """
    Given an integer matrix, find the length of the longest increasing path.
    From each cell, you can either move to four directions: left, right, up or
    down.
    You may NOT move diagonally or move outside of the boundary (i.e.
    wrap-around is not allowed).
    """

    def longestIncreasingPath(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: int
        """
        maxPath = 0
        # The boundary.
        if matrix:
            lenRow = len(matrix)
            lenCol = len(matrix[0])
            # Create a copy of the given matrix, where the elements are -1.
            visitedPath = [[0] * len(matrix[0]) for _ in range(len(matrix))]
            # Do DFS (or BFS, A*, ...whatever) to every element in the matrix.
            for row in range(lenRow):
                for col in range(lenCol):
                    maxPath = max(maxPath, self.doDFS(matrix,
                                                      lenRow - 1,
                                                      lenCol - 1,
                                                      None,
                                                      (row, col),
                                                      visitedPath))
            return maxPath
        else:
            return 0

    def doDFS(self, mat, maxRow, maxCol, prevPath, currPath, visitedPath):
        """
        :param mat: List[List[int]]
        :param prevPath: (row, col) tuple
        :param currPath: (row, col) tuple
        :param visitedPath: List[List[int]], the memorization matrix.
        longest increasing path as the value.
        :return: int, the longest increasing path.
        """
        # The current traversing row and col.
        currRow = currPath[0]
        currCol = currPath[1]

        if prevPath:
            prevRow = prevPath[0]
            prevCol = prevPath[1]
            if mat[prevRow][prevCol] >= mat[currRow][currCol]:
                # Stop when the value of current node isn't greater than the
                # previous one.
                return 0
        if visitedPath[currRow][currCol]:
            return visitedPath[currRow][currCol]

        # Keep going forward through the paths #################################
        # Look right.
        nextPath = (currRow, min(currCol + 1, maxCol))
        pathR = self.doDFS(mat, maxRow, maxCol, currPath, nextPath, visitedPath)
        # Look down.
        nextPath = (min(currRow + 1, maxRow), currCol)
        pathD = self.doDFS(mat, maxRow, maxCol, currPath, nextPath, visitedPath)
        # Look left.
        nextPath = (currRow, max(currCol - 1, 0))
        pathL = self.doDFS(mat, maxRow, maxCol, currPath, nextPath, visitedPath)
        # Look up.
        nextPath = (max(currRow - 1, 0), currCol)
        pathU = self.doDFS(mat, maxRow, maxCol, currPath, nextPath, visitedPath)

        # Going backward to the visited paths ##################################
        maxPath = max(max(pathR, pathD), max(pathL, pathU))
        if maxPath:
            visitedPath[currRow][currCol] = maxPath + 1
        else:
            visitedPath[currRow][currCol] = 1
        return visitedPath[currRow][currCol]

Application Sample

  • To find the largest closing path from a given binary image.

All posts · Home