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
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
Focus on handling minimal and boundary inputs correctly.
Watch out for common algorithmic pitfalls like greedy traps and indexing errors.
Ensure your solution is efficient enough to handle large inputs within time limits.
t1_01basic
Input{"matrix":[[2,1,3],[6,5,4],[7,8,9]]}
Expected13
⏱ Performance - must finish in 2000ms
One minimum falling path is 1 → 5 → 7 with sum 13.
💡 Think about dynamic programming on a grid to accumulate minimum sums.
💡 For each cell, consider the minimum of the three possible cells above it.
💡 Use dp[i][j] = matrix[i][j] + min(dp[i-1][j], dp[i-1][j-1], dp[i-1][j+1]) with boundary checks.
Why it failed: Incorrect output means the recurrence relation is wrong or boundary conditions are mishandled. Fix by ensuring dp updates consider only valid adjacent columns.
✓ Correctly computes minimum falling path sum using proper DP recurrence.
t1_02basic
Input{"matrix":[[-1,2,3],[4,-5,6],[7,8,-9]]}
Expected-15
⏱ Performance - must finish in 2000ms
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.
💡 Negative values can reduce the path sum; don't ignore them.
💡 Check all three possible moves from each cell to find minimum sum.
💡 Remember to handle negative numbers correctly in your DP updates.
Why it failed: Failing this test usually means ignoring negative values or not checking all adjacent columns. Fix by including all three adjacent cells in the min calculation.
✓ Handles negative values and adjacency correctly for minimum path sum.
t2_01edge
Input{"matrix":[[42]]}
Expected42
⏱ Performance - must finish in 2000ms
Single element matrix; minimum falling path sum is the element itself.
💡 Consider the base case when matrix size is 1x1.
💡 DP should handle n=1 without errors or loops.
💡 Return the single element directly if n=1.
Why it failed: Fails single element case by assuming multiple rows or columns. Fix by adding base case for n=1 returning matrix[0][0].
✓ Correctly handles single element matrix.
t2_02edge
Input{"matrix":[[-10,-10],[-10,-10]]}
Expected-20
⏱ Performance - must finish in 2000ms
All elements negative; minimum path sums all negative values, e.g. -10 + -10 = -20.
💡 Negative values do not invalidate the DP approach.
💡 Ensure min calculations do not default to zero or positive values.
💡 DP must correctly accumulate negative sums.
Why it failed: Fails negative values by initializing DP with zeros or positive infinity incorrectly. Fix by initializing DP with matrix values and using min properly.
✓ Correctly computes minimum path sum with negative values.
t2_03edge
Input{"matrix":[[5,5,5],[5,5,5],[5,5,5]]}
Expected15
⏱ Performance - must finish in 2000ms
All elements equal; minimum path sum is n times that element (3*5=15).
💡 Uniform values simplify the problem but still test correctness.
💡 DP should not rely on value differences to function.
💡 Check that DP sums correctly even when all values are equal.
Why it failed: Fails uniform matrix by incorrectly updating DP or skipping some cells. Fix by ensuring all cells are processed and minimum is computed correctly.
✓ Correctly handles uniform value matrices.
t3_01corner
Input{"matrix":[[1,100,1],[100,1,100],[1,100,1]]}
Expected3
⏱ Performance - must finish in 2000ms
Greedy approach picking minimum in each row fails; correct path is 1 → 1 → 1 with sum 3.
💡 Greedy choice of minimum in each row may not yield global minimum.
💡 DP must consider all adjacent columns, not just local minima.
💡 Use full DP recurrence to avoid greedy trap.
Why it failed: Fails due to greedy approach picking local minima ignoring adjacency constraints. Fix by implementing DP considering all three adjacent positions per row.
✓ Avoids greedy trap by using full DP adjacency checks.
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.
💡 Check boundary conditions when accessing j-1 and j+1 columns.
💡 Avoid index out-of-range errors by validating column indices.
💡 Ensure DP updates only valid adjacent columns.
Why it failed: Fails due to off-by-one errors accessing invalid columns. Fix by adding boundary checks before accessing dp[i-1][j-1] and dp[i-1][j+1].
✓ Correctly handles boundary columns without index errors.
t3_03corner
Input{"matrix":[[1,2,3],[1,2,3],[1,2,3]]}
Expected3
⏱ Performance - must finish in 2000ms
Tests confusion between 0/1 and unbounded knapsack style; each row must pick exactly one element adjacent to previous, no repeats in same row.
💡 Each row must pick exactly one element; no skipping rows.
💡 DP must accumulate sums row by row, not reuse elements arbitrarily.
💡 Avoid treating problem like unbounded knapsack; enforce row progression.
Why it failed: Fails by allowing skipping rows or multiple picks per row. Fix by iterating row-wise and picking exactly one adjacent element per row.
✓ Correctly enforces one pick per row with adjacency.
t4_01performance
Input{"_description":"n=1000 at constraint boundary - executor generates this"}
Expectednull
⏱ Performance - must finish in 2000ms
n=1000, O(n^2) DP must complete within 2 seconds.
💡 Use bottom-up DP with O(n^2) time complexity.
💡 Avoid recursion or exponential brute force.
💡 Optimize space by reusing previous row's DP array.
Why it failed: TLE due to exponential brute force or inefficient recursion. Fix by implementing O(n^2) DP with memoization or tabulation.
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
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.
Step 2: Identify suitable algorithm
Dynamic programming over intervals (interval DP) systematically explores all sub-polygons and stores minimal costs, ensuring optimality.
Final Answer:
Option D -> Option D
Quick Check:
Interval DP is the classic approach for polygon triangulation problems [OK]
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
Step 1: Understand problem constraints
The problem requires counting all unique paths with only right and down moves, which naturally forms overlapping subproblems.
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.
Final Answer:
Option C -> Option C
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
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'.
Step 2: Understand impact
Using dp[j-1] twice ignores the diagonal value 'prev', causing incorrect dp values and max square size.
Final Answer:
Option A -> Option A
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
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.
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].
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.
Final Answer:
Option A -> Option A
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 unknownstrongwhile earning +1 Grip toward your certificate.