class Solution:
def minimumTotal(self, triangle):
if not triangle:
return 0
# Start from the second last row and move upwards
for row in range(len(triangle) - 2, -1, -1):
for col in range(len(triangle[row])):
# Update the current value to be the sum of itself and the min of the two below
triangle[row][col] += min(triangle[row + 1][col], triangle[row + 1][col + 1])
# The top element now contains the minimum path sum
return triangle[0][0]
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
if (n == 0) return 0;
// Start from the second last row and move upwards
for (int row = n - 2; row >= 0; --row) {
for (int col = 0; col < triangle[row].size(); ++col) {
triangle[row][col] += min(triangle[row + 1][col], triangle[row + 1][col + 1]);
}
}
return triangle[0][0];
}
};
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int n = triangle.size();
if (n == 0) return 0;
// Start from the second last row and move upwards
for (int row = n - 2; row >= 0; row--) {
for (int col = 0; col < triangle.get(row).size(); col++) {
int val = triangle.get(row).get(col) +
Math.min(triangle.get(row + 1).get(col), triangle.get(row + 1).get(col + 1));
triangle.get(row).set(col, val);
}
}
return triangle.get(0).get(0);
}
}
var minimumTotal = function(triangle) {
if (triangle.length === 0) return 0;
// Start from the second last row and move upwards
for (let row = triangle.length - 2; row >= 0; row--) {
for (let col = 0; col < triangle[row].length; col++) {
triangle[row][col] += Math.min(triangle[row + 1][col], triangle[row + 1][col + 1]);
}
}
return triangle[0][0];
};
You are given a triangle array triangle
where triangle[i]
represents the elements on the i
th row of the triangle. Each step, you may move to an adjacent number on the row below (i.e., from element triangle[i][j]
, you can move to either triangle[i+1][j]
or triangle[i+1][j+1]
).
Your task is to find the minimum path sum from the top to the bottom of the triangle. You must start at the top element and move only to adjacent numbers on the row below, until you reach the last row. The triangle is guaranteed to have at least one row, and all elements are integers.
At first glance, the problem seems to require checking every possible path from the top to the bottom of the triangle and finding the one with the smallest sum. This is a classic example of a problem that can be approached with recursion or brute-force, but such methods quickly become inefficient as the triangle grows larger, due to the exponential number of possible paths.
To optimize, we can notice that the minimum path to reach a cell in the triangle depends on the minimum paths to reach the cells above it. This overlapping subproblem structure suggests that dynamic programming is a good fit.
Instead of recalculating the minimum path for each cell repeatedly, we can store and reuse results for subproblems we've already solved. By working from the bottom of the triangle upwards, we can iteratively calculate the minimum path sum for each cell, eventually reaching the top with the answer.
Step-by-step:
Consider the triangle:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
The Triangle problem is a classic dynamic programming challenge that demonstrates how recognizing overlapping subproblems and optimal substructure can lead to efficient solutions. By starting from the bottom and working upwards, we avoid redundant calculations and achieve a time and space-efficient algorithm. The key insight is to reuse results for subproblems, updating each cell with the minimum sum path to the bottom, and ending with the answer at the top of the triangle.