Close Menu
    Code and Debug
    • Home
    • Our Courses
    • Blog
    • About Us
    • Contact Us
    Facebook X (Twitter) Instagram YouTube WhatsApp
    • Home
    • Our Courses
    • Blog
    • About Us
    • Contact Us
    Facebook Instagram YouTube LinkedIn WhatsApp
    Code and Debug – BlogCode and Debug – Blog
    Code and Debug – BlogCode and Debug – Blog
    Home»Data Structures & Algorithms»Minimum Falling Path Sum | Leetcode 931 | Variable Starting and Ending Points
    Data Structures & Algorithms

    Minimum Falling Path Sum | Leetcode 931 | Variable Starting and Ending Points

    codeanddebugBy codeanddebug4 August 2025No Comments7 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
    Featured image of a question to solve minimum falling path sum
    Share
    Facebook Twitter LinkedIn Pinterest Email

    Given an n x n array of integers matrix, return the minimum sum of any falling path through matrix.

    A falling path starts at any element in the first row and chooses the element in the next row that is either directly below or diagonally left/right. Specifically, the next element from position (row, col) will be (row + 1, col - 1), (row + 1, col), or (row + 1, col + 1).

    Here’s the [Problem Link] to begin with.

    Example 1:

    Input: matrix = [[2,1,3],[6,5,4],[7,8,9]]
    Output: 13
    Explanation: There are two falling paths with a minimum sum as shown.

    Example 2:

    Input: matrix = [[-19,57],[-40,-5]]
    Output: -59
    Explanation: The falling path with a minimum sum is shown.

    Constraints:

    • n == matrix.length == matrix[i].length
    • 1 <= n <= 100
    • -100 <= matrix[i][j] <= 100
    Contents:
     [show]
    • Solution 1: Brute Force (Recursion)
      • Intuition
      • Approach
      • Code
      • Code Explanation
      • Time and Space Complexity
      • Simplified
    • Solution 2: Memoization (Top-Down DP)
      • Intuition
      • Approach
      • Code
      • Code Explanation
      • Time and Space Complexity
      • Simplified
    • Solution 3: Tabulation (Bottom-Up DP)
      • Intuition
      • Approach
      • Code
      • Code Explanation
      • Time and Space Complexity
      • Simplified
    • Solution 4: Tabulation (Space Optimization)
      • Intuition
      • Approach
      • Code
      • Code Explanation
      • Time and Space Complexity
      • Simplified
    • Summary Table
    • Conclusion

    Solution 1: Brute Force (Recursion)

    Intuition

    At cell (i, j), you have three choices moving up the rows:

    • Move from top-left (i-1, j-1)
    • Move from top (i-1, j)
    • Move from top-right (i-1, j+1)
      Try all possible paths recursively for every starting position in the last row, and take the minimum.

    Approach

    • Base case: If you’ve moved out of bounds (j < 0 or j ≥ columns), return infinity. If you’re at the top row, return the matrix value.
    • Recursive case: From each cell, calculate sum using left, up, and right moves; add current cell’s value and propagate min sum upward.

    Code

    class Solution:
        def solve(self, i, j, matrix):
            # Out of bounds, set as infinite to avoid considering
            if j < 0 or j >= len(matrix[0]):
                return float("inf")
            # Top row: path sum is just the value itself
            if i == 0:
                return matrix[0][j]
            # Take min of possible paths to (i, j)
            left = self.solve(i - 1, j - 1, matrix)
            up = self.solve(i - 1, j, matrix)
            right = self.solve(i - 1, j + 1, matrix)
            # Return cell value plus min path sum from above
            return matrix[i][j] + min(left, up, right)
    
        def minFallingPathSum(self, matrix: List[List[int]]) -> int:
            rows = len(matrix)
            cols = len(matrix[0])
            mini = float("inf")
            # Try each position in the last row as an end point
            for j in range(cols):
                mini = min(mini, self.solve(rows - 1, j, matrix))
            return mini

    Code Explanation

    • From every possible last cell in the bottom row, recursively compute all valid upward falling paths.
    • Every call checks three possible “moves”: from diagonal left, above, or diagonal right.
    • The recursion explores every path, returning the minimum overall.

    Time and Space Complexity

    • Time: O(3^rows) (because each step recursively branches into up to three calls)
    • Space: O(rows) (stack recursion depth)

    Simplified

    A pure, all-paths brute force. Simple for small matrices, but very inefficient for larger ones.


    Solution 2: Memoization (Top-Down DP)

    Intuition

    Many subproblems (“min path sum from position (i, j)”) repeat, so use a DP table dp[i][j] to store computed answers. Always check if a sub-result was computed before recursing!

    Approach

    • Create a DP grid, initialized to None.
    • Before each recursion, see if result for that position exists. If so, just return it!
    • Save and reuse results to avoid redundant computation.

    Code

    class Solution:
        def solve(self, i, j, matrix, dp):
            # Out of bounds in column
            if j < 0 or j >= len(matrix[0]):
                return float("inf")
            # Top row
            if i == 0:
                return matrix[0][j]
            # If already computed, use memoized result
            if dp[i][j] is not None:
                return dp[i][j]
            # Compute possible paths
            left = matrix[i][j] + self.solve(i - 1, j - 1, matrix, dp)
            up = matrix[i][j] + self.solve(i - 1, j, matrix, dp)
            right = matrix[i][j] + self.solve(i - 1, j + 1, matrix, dp)
            dp[i][j] = min(left, up, right)
            return dp[i][j]
    
        def minFallingPathSum(self, matrix: List[List[int]]) -> int:
            rows = len(matrix)
            cols = len(matrix[0])
            dp = [[None for _ in range(cols)] for _ in range(cols)]
            mini = float("inf")
            for j in range(cols):
                mini = min(mini, self.solve(rows - 1, j, matrix, dp))
            return mini

    Code Explanation

    • For every bottom cell, recursively finds min falling path sum but now with memorization.
    • Memoization grid dp[i][j] means every cell is solved once and then reused.
    • Significantly speeds up brute force, ideal for larger matrices.

    Time and Space Complexity

    • Time: O(rows × cols)
    • Space: O(rows × cols) for dp + O(rows) stack

    Simplified

    No recalculation, no waste. Typical recursive DP, great for clarity and speed!


    Solution 3: Tabulation (Bottom-Up DP)

    Intuition

    Work from top row downward, filling a DP table:
    At every cell in row i, col j: take the cell value plus the minimal path from top, top-left, and top-right of the previous row.

    Approach

    • DP grid dp[i][j]: min path sum to (i, j) from row 0.
    • Set dp[j] = matrix[j] for all columns (base case).
    • For all rows:
      • For leftmost column, top-left is infinity.
      • For rightmost column, top-right is infinity.
      • Each cell: add cell value + min(left, up, right).

    Code

    class Solution:
        def minFallingPathSum(self, matrix: List[List[int]]) -> int:
            rows = len(matrix)
            cols = len(matrix[0])
            dp = [[None for _ in range(cols)] for _ in range(rows)]
            # Base case: top row same as matrix
            for j in range(cols):
                dp[0][j] = matrix[0][j]
            # Fill for each row below
            for i in range(1, rows):
                for j in range(0, cols):
                    # For leftmost, top-left is invalid
                    if j == 0:
                        left = float("inf")
                    else:
                        left = matrix[i][j] + dp[i - 1][j - 1]
                    # Always valid: up
                    up = matrix[i][j] + dp[i - 1][j]
                    # For rightmost, top-right is invalid
                    if j == cols - 1:
                        right = float("inf")
                    else:
                        right = matrix[i][j] + dp[i - 1][j + 1]
                    # Store minimum path sum for cell
                    dp[i][j] = min(left, up, right)
            # Minimum in the last row is the answer
            mini = float("inf")
            for j in range(cols):
                mini = min(mini, dp[rows - 1][j])
            return mini

    Code Explanation

    • Start with the first row’s values (base).
    • For each cell, consider three reachable cells from the previous row.
    • Fill the DP table row by row; last row contains the min answers.

    Time and Space Complexity

    • Time: O(rows × cols)
    • Space: O(rows × cols)

    Simplified

    Classic bottom-up DP; reliable, easy to debug, and clear state transitions.


    Solution 4: Tabulation (Space Optimization)

    Intuition

    You only need the previous row to compute the current row. Use two 1D arrays (prev and curr), rolling through the matrix row by row.

    Approach

    • prev[j] contains DP values for previous row.
    • For each row, fill out a new current array, then assign curr to prev for the next row.
    • Final row only in prev.

    Code

    class Solution:
        def minFallingPathSum(self, matrix: List[List[int]]) -> int:
            rows = len(matrix)
            cols = len(matrix[0])
            prev = [None for _ in range(cols)]
            # Initialize with the first row
            for j in range(cols):
                prev[j] = matrix[0][j]
            # For each row below, use rolling arrays
            for i in range(1, rows):
                curr = [None] * cols
                for j in range(0, cols):
                    # For leftmost, top-left is invalid
                    if j == 0:
                        left = float("inf")
                    else:
                        left = matrix[i][j] + prev[j - 1]
                    # Always valid: up
                    up = matrix[i][j] + prev[j]
                    # For rightmost, top-right is invalid
                    if j == cols - 1:
                        right = float("inf")
                    else:
                        right = matrix[i][j] + prev[j + 1]
                    # Set the min sum for this cell
                    curr[j] = min(left, up, right)
                prev = curr
            # Minimum in last row
            mini = float("inf")
            for j in range(cols):
                mini = min(mini, prev[j])
            return mini

    Code Explanation

    • Saves on space by needing only one prior row’s DP state.
    • Efficient and optimal for coding interviews with size constraints.

    Time and Space Complexity

    • Time: O(rows × cols)
    • Space: O(cols) (just two arrays per step)

    Simplified

    Ultra-useful rolling array DP pattern, especially for large matrices!


    Summary Table

    ApproachTimeSpaceBest For
    Recursion (Brute Force)O(3^rows)O(rows)Learning, small size
    Memoization (Top-Down DP)O(rows·cols)O(rows·cols)Efficient, readable
    Tabulation (Bottom-Up DP)O(rows·cols)O(rows·cols)Systematic DP
    Space-Optimized TabulationO(rows·cols)O(cols)Large limits, coding

    Conclusion

    Minimum Falling Path Sum is an excellent test of dynamic programming mastery. Start with recursion, then build up to memoization and tabulation, and always end with the most space-optimal version for real interview success. Practice with more DP problems and always look for ways to reduce space without sacrificing clarity!

    Join our Advance DSA COURSE

    For any changes to the article, kindly email at code@codeanddebug.in or contact us at +91-9712928220.

    Dynamic Programming on 2D Arrays Medium
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Previous ArticleTriangle | Leetcode 120 | All 4 DP Solutions
    codeanddebug
    • Website

    Related Posts

    Data Structures & Algorithms

    Triangle | Leetcode 120 | All 4 DP Solutions

    4 August 2025
    Data Structures & Algorithms

    Minimum Path Sum | Leetcode 64 | All 4 DP Solutions

    2 August 2025
    Data Structures & Algorithms

    Unique Paths II | Leetcode 63 | All 4 DP Solutions

    2 August 2025
    Add A Comment
    Leave A Reply Cancel Reply

    Categories
    • Data Structures & Algorithms (168)
      • Beginner (62)
      • Expert (39)
      • Intermediate (67)
    • Uncategorised (1)
    Recent Posts

    Minimum Falling Path Sum | Leetcode 931 | Variable Starting and Ending Points

    4 August 2025

    Triangle | Leetcode 120 | All 4 DP Solutions

    4 August 2025

    Minimum Path Sum | Leetcode 64 | All 4 DP Solutions

    2 August 2025

    Unique Paths II | Leetcode 63 | All 4 DP Solutions

    2 August 2025

    Unique Paths | Leetcode 62 | All 4 DP Solutions

    2 August 2025
    Facebook Instagram YouTube LinkedIn WhatsApp
    © 2025 Code and Debug. All rights reserved.

    Type above and press Enter to search. Press Esc to cancel.