Leetcode 1289. Minimum Falling Path Sum II

Problem Explanation:

The problem is to find the minimum falling path sum in a square grid where each falling path consists of exactly one element from each row of the grid and no two elements chosen in adjacent rows are in the same column. For example, if we have a grid:

1
2plaintext
31 2 3
44 5 6
57 8 9

Then a possible falling path could be [1,5,7] and its corresponding sum is 13. In this case, this is the minimum possible sum, so the result for this input should be 13.

The problem can be solved in a dynamic programming manner. We iterate from the second row to the last row and for each cell, we add to it the minimum of the previous row excluding the element in the same column to avoid taking two elements in the same column in consecutive rows. After finishing this, the minimum element in the last row is our answer because it's the end of the path with minimum sum.

We can notice that the maximum number of elements in each row is 200, and so we need only to keep track of the minimum element and the second minimum element because in the worst-case scenario we can't take the minimum element (if it's in the same column of the current cell) so we take the second minimum element.

Python Solution:

1
2python
3class Solution:
4    def minFallingPathSum(self, arr):
5        prev = arr[0]
6        for row in arr[1:]:
7            new = []
8            for j in range(len(row)):
9                new.append(min(prev[i] for i in range(len(row)) if i != j) + row[j])
10            prev = new
11        return min(prev)

Java Solution:

1
2java
3class Solution {
4    public int minFallingPathSum(int[][] arr) {
5        int n = arr.length;
6        int[][] dp = new int[n][n];
7        int res = Integer.MAX_VALUE, min1 = -1, min2 = -1;
8
9        for (int r = 0; r < n; ++r)
10            for (int c = 0; c < n; ++c) {
11                if (r > 0) {
12                    dp[r][c] = arr[r][c] 
13                              + (c == min1 ? dp[r - 1][min2] : dp[r - 1][min1]);
14
15                    if (dp[r][c] < res)
16                        res = dp[r][c];
17                } 
18                else
19                    dp[r][c] = arr[r][c];
20            }
21        
22        return res;
23    }
24}

JavaScript Solution:

1
2javascript
3var minFallingPathSum = function(arr) {
4  let len = arr.length;
5  if (len === 1) return arr[0][0];
6
7  let dp = arr[0].slice();
8
9  for(let i = 1; i < len; i++){
10    let preDp = dp.slice();
11    for(let j = 0; j < len; j++){
12      dp[j] = arr[i][j] + Math.min(...preDp.slice(0, j).concat(preDp.slice(j + 1)));
13    }
14  }
15
16  return Math.min(...dp);
17};

C++ Solution:

1
2cpp
3class Solution {
4public:
5    int minFallingPathSum(vector<vector<int>>& arr) {
6        int N = arr.size();
7        for (int i = N - 2; i >= 0; --i) {
8            for (int j = 0; j < N; ++j) {
9                int left = (j > 0) ? arr[i + 1][j - 1] : INT_MAX;
10                int mid = arr[i + 1][j];
11                int right = (j + 1 < N) ? arr[i + 1][j + 1] : INT_MAX;
12                arr[i][j] += min({left, mid, right});
13            }
14        }
15        return *min_element(arr[0].begin(), arr[0].end());
16    }
17};

C# Solution:

1
2csharp
3public class Solution {
4    public int MinFallingPathSum(int[][] A) {
5        int n = A.Length;
6        for (int i = 1; i < n; i ++) {
7            Array.Sort(A[i - 1]);
8            for (int j = 0; j < n; j ++) {
9                A[i][j] += A[i - 1][Math.Min(j, 1)];
10            }
11        }
12        Array.Sort(A[n - 1]);
13        return A[n - 1][0];
14    }
15}

In all the solutions above, we first initialize a dp array or copy the first row of the input array as the starting path sum. Then, for each row, the sum at each position is updated as the current number plus the minimum path sum in the above row, excluding the current column position. And finally, the minimum path sum from the last row is returned.All the solutions above utilize a dynamic programming approach to simplify the problem. They start from the top row and move downwards, at each step calculating the minimum falling path sum to reach that cell based on the previous row's sums. The excluding condition (to avoid two elements in the same column from being in consecutive rows) is maintained by choosing the minimum from the cells not in the current column.

The time complexity for each of these solutions is O(N^2), where N is the number of rows/columns in the grid. This is because we have a double for loop which iterates over the entire grid. The space complexity is also O(N^2) due to the use of a DP table of the same size as the input grid.

It's essential to note that while not immediately intuitive, the key insight to solve this problem is understanding that the final minimum path sum will end up at one of the cells in the final row. Hence, our task reduces to computing the minimum sum that ends up at each of these cells.

The Python, Java, JavaScript, C++ and C# solutions given above handle this effectively by leveraging dynamic programming. They iteratively compute the minimum path sum leading up to each cell, thereby building up on answers for smaller sub-problems to solve the larger problem. In the process, they ensure no two elements chosen in adjacent rows are in the same column, which adheres to the constraints of the task. After filling up the DP table, these solutions return the minimum value from the final row, which represents the minimum falling path sum in the grid.


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫