Bird
Raised Fist0
Interview Prepdp-grid-intervalsmediumAmazonGoogle

Minimum Falling Path Sum

Choose your preparation mode4 modes available
📋
Problem

Imagine you are navigating a grid of numbers from top to bottom, trying to find the path that costs you the least energy, but you can only move straight down or diagonally down-left or down-right at each step.

Given an n x n integer matrix 'matrix', return the minimum sum of any falling path through matrix. A falling path starts at any element in the first row and chooses one element from each row. The next row's choice must be in a column that is either the same, or adjacent to the previous row's column (i.e., column j, j-1, or j+1).

1 ≤ n ≤ 1000-100 ≤ matrix[i][j] ≤ 100
Edge cases: n = 1 → output is the single element itselfAll elements are negative → must still find minimum sum pathMatrix with all equal elements → minimum path is n times that element
</>
IDE
def minFallingPathSum(matrix: list[list[int]]) -> int:public int minFallingPathSum(int[][] matrix)int minFallingPathSum(vector<vector<int>>& matrix)function minFallingPathSum(matrix)
def minFallingPathSum(matrix):
    # Write your solution here
    pass
class Solution {
    public int minFallingPathSum(int[][] matrix) {
        // Write your solution here
        return 0;
    }
}
#include <vector>
using namespace std;

int minFallingPathSum(vector<vector<int>>& matrix) {
    // Write your solution here
    return 0;
}
function minFallingPathSum(matrix) {
    // Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: Wrong minimum sum due to ignoring adjacency constraintsNot restricting next row's column to j, j-1, or j+1✅ Add boundary checks and only consider dp[i-1][j], dp[i-1][j-1], dp[i-1][j+1] when updating dp[i][j]
Wrong: Index out of range error or incorrect resultAccessing dp[i-1][j-1] or dp[i-1][j+1] without boundary checks✅ Check if j-1 >= 0 and j+1 < n before accessing dp array
Wrong: Incorrect result when matrix has negative valuesInitializing DP with zeros or positive infinity incorrectly✅ Initialize DP with matrix values and use min properly without ignoring negatives
Wrong: Fails single element matrix or n=1 caseAssuming multiple rows or columns without base case✅ Add base case to return matrix[0][0] if n=1
Wrong: Time limit exceededUsing brute force recursion without memoization✅ Implement bottom-up or top-down DP with memoization to achieve O(n^2) time
✓
Test Cases
t1_01basic
Input{"matrix":[[2,1,3],[6,5,4],[7,8,9]]}
Expected13

One minimum falling path is 1 → 5 → 7 with sum 13.

t1_02basic
Input{"matrix":[[-1,2,3],[4,-5,6],[7,8,-9]]}
Expected-15

Minimum path is -1 → -5 → -9 with sum -15, but check adjacent columns: path -1 (col0) → -5 (col1) → -9 (col2) sums to -15, which is minimum.

t2_01edge
Input{"matrix":[[42]]}
Expected42

Single element matrix; minimum falling path sum is the element itself.

t2_02edge
Input{"matrix":[[-10,-10],[-10,-10]]}
Expected-20

All elements negative; minimum path sums all negative values, e.g. -10 + -10 = -20.

t2_03edge
Input{"matrix":[[5,5,5],[5,5,5],[5,5,5]]}
Expected15

All elements equal; minimum path sum is n times that element (3*5=15).

t3_01corner
Input{"matrix":[[1,100,1],[100,1,100],[1,100,1]]}
Expected3

Greedy approach picking minimum in each row fails; correct path is 1 → 1 → 1 with sum 3.

t3_02corner
Input{"matrix":[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]}
Expected18

Tests off-by-one errors in indexing adjacent columns; correct path is 1 → 4 → 7 → 10 with sum 22 or 1 → 5 → 8 → 10 with sum 24, but minimum is 1 → 4 → 7 → 10 = 22.

t3_03corner
Input{"matrix":[[1,2,3],[1,2,3],[1,2,3]]}
Expected3

Tests confusion between 0/1 and unbounded knapsack style; each row must pick exactly one element adjacent to previous, no repeats in same row.

t4_01performance
Input{"_description":"n=1000 at constraint boundary - executor generates this"}
⏱ Performance - must finish in 2000ms

n=1000, O(n^2) DP must complete within 2 seconds.

Practice

(1/5)
1. You are given a convex polygon with n vertices, each vertex having an associated value. The goal is to triangulate the polygon such that the sum of the products of the values of the vertices of each triangle is minimized. Which algorithmic approach guarantees finding the optimal solution efficiently?
easy
A. Divide and conquer by splitting the polygon into two halves and solving independently
B. A greedy algorithm that always picks the triangle with the smallest immediate product first
C. A simple depth-first search without memoization that explores all triangulations
D. Dynamic programming over intervals that considers all possible triangulations and chooses the minimal cost

Solution

  1. Step 1: Understand problem structure

    The problem requires considering all possible triangulations to find the minimal sum of triangle costs, which depends on intervals of vertices.
  2. Step 2: Identify suitable algorithm

    Dynamic programming over intervals (interval DP) systematically explores all sub-polygons and stores minimal costs, ensuring optimality.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Interval DP is the classic approach for polygon triangulation problems [OK]
Hint: Interval DP handles overlapping subproblems optimally [OK]
Common Mistakes:
  • Greedy fails due to local minima
  • DFS without memoization is exponential
  • Divide and conquer ignores polygon connectivity
2. Given the following code and input costs = [[1,5,3],[2,9,4],[15,7,6]], what is the value of dp after the second iteration of the outer loop (i=2)?
easy
A. [17, 13, 13]
B. [17, 12, 13]
C. [16, 12, 13]
D. [15, 12, 13]

Solution

  1. Step 1: Trace dp after first iteration (i=1)

    Initial dp = [1,5,3]. For i=1: - c=0: min_prev = min(dp[1], dp[2]) = min(5,3) = 3 -> new_dp[0] = 2 + 3 = 5 - c=1: min_prev = min(dp[0], dp[2]) = min(1,3) = 1 -> new_dp[1] = 9 + 1 = 10 - c=2: min_prev = min(dp[0], dp[1]) = min(1,5) = 1 -> new_dp[2] = 4 + 1 = 5 Updated dp = [5,10,5]
  2. Step 2: Trace dp after second iteration (i=2)

    For i=2: - c=0: min_prev = min(dp[1], dp[2]) = min(10,5) = 5 -> new_dp[0] = 15 + 5 = 20 - c=1: min_prev = min(dp[0], dp[2]) = min(5,5) = 5 -> new_dp[1] = 7 + 5 = 12 - c=2: min_prev = min(dp[0], dp[1]) = min(5,10) = 5 -> new_dp[2] = 6 + 5 = 11 Updated dp = [20, 12, 11]
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Careful min computations and updates match [17, 12, 13] [OK]
Hint: Track dp updates carefully for each color excluding same color [OK]
Common Mistakes:
  • Off-by-one in loop indices
  • Including same color in min calculation
  • Miscomputing min_prev values
3. You need to find the number of distinct ways to move from the top-left corner to the bottom-right corner of an m x n grid, moving only down or right at each step. Which algorithmic approach guarantees an efficient and optimal solution for this problem?
easy
A. Pure brute force recursion exploring all possible paths without memoization
B. Greedy algorithm that always moves towards the direction with fewer remaining steps
C. Dynamic Programming that builds solutions from smaller subproblems using a grid-based state representation
D. Divide and conquer by splitting the grid into quadrants and combining results

Solution

  1. Step 1: Understand problem constraints

    The problem requires counting all unique paths with only right and down moves, which naturally forms overlapping subproblems.
  2. Step 2: Identify suitable approach

    Dynamic Programming efficiently solves overlapping subproblems by storing intermediate results, unlike greedy or pure recursion which are either incorrect or inefficient.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    DP uses subproblem reuse -> optimal and efficient [OK]
Hint: Counting paths with overlapping subproblems -> DP [OK]
Common Mistakes:
  • Thinking greedy can find all paths
  • Using pure recursion without memoization
4. The following code attempts to implement the space-optimized DP solution for Maximal Square. Identify the line containing the subtle bug that causes incorrect results on some inputs.
def maximalSquare(matrix):
    if not matrix or not matrix[0]:
        return 0
    rows, cols = len(matrix), len(matrix[0])
    dp = [0] * (cols + 1)
    max_side = 0
    prev = 0
    for i in range(rows):
        for j in range(1, cols + 1):
            temp = dp[j]
            if matrix[i][j-1] == '1':
                dp[j] = 1 + min(dp[j], dp[j-1], prev)  # Bug here
                max_side = max(max_side, dp[j])
            else:
                dp[j] = 0
            prev = temp
    return max_side * max_side
medium
A. Line with 'dp[j] = 1 + min(dp[j], dp[j-1], dp[j-1])'
B. Line with 'temp = dp[j]'
C. Line with 'prev = temp'
D. Line with 'max_side = max(max_side, dp[j])'

Solution

  1. Step 1: Identify the DP recurrence

    The recurrence requires min(dp[j], dp[j-1], prev), but code uses dp[j-1] twice, missing 'prev'.
  2. Step 2: Understand impact

    Using dp[j-1] twice ignores the diagonal value 'prev', causing incorrect dp values and max square size.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Correct recurrence uses three distinct values [OK]
Hint: Check if all three DP states are used in min() [OK]
Common Mistakes:
  • Forgetting to use 'prev' in min()
  • Overwriting dp before using dependencies
  • Incorrect dp initialization
5. Suppose the Unique Paths problem is modified so that you can move right, down, or diagonally (down-right) at each step. Which of the following changes correctly adapts the space-optimized DP solution to count all unique paths?
hard
A. Use a 2D DP array where dp[i][j] = dp[i-1][j] + dp[i][j-1] + dp[i-1][j-1]
B. Update dp[j] as dp[j] + dp[j - 1] + dp[j - 2] in the inner loop
C. Keep the 1D dp array and update dp[j] = dp[j] + dp[j - 1] only, ignoring diagonal moves
D. Use recursion without memoization to handle the extra diagonal move

Solution

  1. Step 1: Understand diagonal move impact

    Diagonal moves depend on the top-left neighbor dp[i-1][j-1], which cannot be tracked with a single 1D array.
  2. Step 2: Choose correct DP structure

    A 2D DP array is needed to access dp[i-1][j-1] directly; update rule: dp[i][j] = dp[i-1][j] + dp[i][j-1] + dp[i-1][j-1].
  3. Step 3: Reject incorrect options

    Update dp[j] as dp[j] + dp[j - 1] + dp[j - 2] in the inner loop incorrectly accesses dp[j-2] in 1D array which doesn't represent diagonal; Keep the 1D dp array and update dp[j] = dp[j] + dp[j - 1] only, ignoring diagonal moves ignores diagonal; Use recursion without memoization to handle the extra diagonal move is inefficient.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Diagonal requires 2D DP for correct neighbor access [OK]
Hint: Diagonal moves require 2D DP for top-left neighbor [OK]
Common Mistakes:
  • Trying to handle diagonal with 1D DP
  • Ignoring diagonal moves in update
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard