Triangle

Medium Dynamic Programming 2D DP - max/min of last row Original on LeetCode

Triangle is a medium dynamic programming problem solved with the 2d dp - max/min of last row pattern. The best approach, optimal (bottom-up in one array), runs in O(n²) time and O(n) space. Below are 2 approaches in Java, from top-down recursion up.

Problem

Given a triangle of numbers, find the minimum path sum from top to bottom. From index j in one row you may move to index j or j + 1 in the next row.

Examples

Example 1

Input
triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
Output
11
Why
2 + 3 + 5 + 1.

Example 2

Input
triangle = [[-10]]
Output
-10

Constraints

  • 1 <= rows <= 200; row i has i + 1 values.
  • From index j you can move to j or j + 1 in the next row.

Animated walkthrough

A narrated, step-by-step animation that builds the solution from the idea up. Press play, or step through it at your own pace.

Concepts first, then the problem and every approach, step by step.

Space to play or pause · ← → to jump a step · click or drag the bar to seek

Solutions

Try it yourself first. Then compare: each approach lists its idea, the steps, its time and space, and the Java code.

ApproachTimeSpace
Top-down recursionO(2ⁿ)O(n)
Optimal (bottom-up in one array)O(n²)O(n)

1Top-down recursion

TimeO(2ⁿ)
SpaceO(n)

best(r, j) = value + min(best(r + 1, j), best(r + 1, j + 1)).

  1. Base: the last row returns its own value.
Java
class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        return best(triangle, 0, 0);
    }

    private int best(List<List<Integer>> t, int r, int j) {
        int v = t.get(r).get(j);
        if (r == t.size() - 1) return v;
        return v + Math.min(best(t, r + 1, j), best(t, r + 1, j + 1));
    }
}

2Optimal (bottom-up in one array)

TimeO(n²)
SpaceO(n)

Copy the last row into dp. For each row above, dp[j] = value + min(dp[j], dp[j + 1]). Reading from the bottom means there is one answer at the top and no need to take a minimum over a row.

  1. dp = copy of the last row.
  2. For r from n - 2 down to 0, for j in 0..r: dp[j] = t[r][j] + min(dp[j], dp[j + 1]).
  3. Return dp[0].
Java
class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();
        int[] dp = new int[n + 1];
        for (int r = n - 1; r >= 0; r--)
            for (int j = 0; j <= r; j++)
                dp[j] = triangle.get(r).get(j) + Math.min(dp[j], dp[j + 1]);
        return dp[0];
    }
}

Edge cases to test

  • Single row
  • Negative numbers

Hints

Hint 1

Work from the bottom row up: every cell becomes its value plus the smaller of its two children. The top cell is the answer.

FAQ

What is the best time complexity for Triangle?

Optimal (bottom-up in one array) runs in O(n²) time and O(n) extra space.

Which pattern does Triangle use?

It is a dynamic programming problem that uses the 2d dp - max/min of last row pattern. Other problems with the same pattern: Minimum Falling Path Sum, Geek's Training.

Is there a brute force solution for Triangle?

Yes. Top-down recursion takes O(2ⁿ) time and O(n) space. best(r, j) = value + min(best(r + 1, j), best(r + 1, j + 1)).

Which edge cases should I test for Triangle?

Single row; Negative numbers.