LeetCode #120 Medium

Triangle

Find the minimum path sum from the top of a triangle to the bottom, moving to adjacent numbers on the row below.

dynamic-programmingarray
Open on LeetCode ↗
02

Intuition

💡

Working top-down feels natural since that is how you read the triangle, but it forces you to track which one or two parents in the row above can reach each cell, plus handling the ragged left and right edges where only one parent exists. Flip the direction: work bottom-up instead. From the second-to-last row upward, every single cell has exactly two children directly below it, no exceptions and no edges to special-case, so dp[i][j] = triangle[i][j] + min(dp[i+1][j], dp[i+1][j+1]) always applies cleanly. The invariant: dp[i][j] is the minimum path sum from cell (i,j) down to the bottom, and by the time you reach row i the row below it is already fully solved. The answer lands in dp[0][0], no post-processing scan required.

03

Approach

1

Seed with the bottom row

dp starts as a copy of the triangle's last row -- the minimum path sum from any bottom cell to the bottom is just that cell's own value.

2

Fill upward

For each row i from the second-to-last up to 0, and each valid column j in that row, set dp[j] = triangle[i][j] + min(dp[j], dp[j+1]) using the dp row just computed for i+1. Every cell has exactly two children, so there are no ragged-edge special cases.

3

Read the top

After processing row 0, dp[0] is the minimum path sum for the whole triangle -- no scanning or additional comparison needed.

04

Solution & live demo

python
1class Solution:
2 def minimumTotal(self, triangle: list[list[int]]) -> int:
3 dp = triangle[-1][:]
4 for i in range(len(triangle) - 2, -1, -1):
5 for j in range(i + 1):
6 dp[j] = triangle[i][j] + min(dp[j], dp[j + 1])
7 return dp[0]
05

Edge cases

Single-row triangle

The loop never runs; the answer is simply that one value.

All negative numbers

min() still correctly favors the least (most negative) sum since no sign assumption is baked into the recurrence.

Two rows

One iteration of the upward fill directly produces dp[0] = triangle[0][0] + min of the two bottom values.

Tie between the two children

min() picks either equally-valid path; the resulting sum is identical either way.

06

Complexity

Time
O(n^2) for n rows
Space
O(n), reusing a single row of dp
Every cell is visited once; bottom-up avoids any parent-tracking bookkeeping.