Given a triangle
array, return the minimum path sum from top to bottom.
For each step, you may move to an adjacent number of the row below. More formally, if you are on index i
on the current row, you may move to either index i
or index i + 1
on the next row.
Example 1:
Input: triangle = [[2],[3,4],[6,5,7],[4,1,8,3]] Output: 11 Explanation: The triangle looks like: 2 3 4 6 5 7 4 1 8 3 The minimum path sum from top to bottom is 2 + 3 + 5 + 1 = 11 (underlined above).
Example 2:
Input: triangle = [[-10]] Output: -10
Constraints:
1 <= triangle.length <= 200
triangle[0].length == 1
triangle[i].length == triangle[i - 1].length + 1
-104 <= triangle[i][j] <= 104
O(n)
extra space, where n
is the total number of rows in the triangle?When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to this problem involves exploring every single possible path from the top to the bottom of the triangle. It's like trying out every route you could take, no matter how silly it seems at first. By checking every possibility, we guarantee we'll find the best one.
Here's how the algorithm would work step-by-step:
def find_minimum_total_brute_force(triangle):
minimum_total = float('inf')
def calculate_path_sum(row_index, column_index, current_path_sum):
nonlocal minimum_total
current_path_sum += triangle[row_index][column_index]
# If we've reached the bottom, check minimum.
if row_index == len(triangle) - 1:
minimum_total = min(minimum_total, current_path_sum)
return
# Explore moving down.
calculate_path_sum(row_index + 1, column_index, current_path_sum)
# Explore moving down and right, if possible.
if column_index + 1 < len(triangle[row_index + 1]):
calculate_path_sum(row_index + 1, column_index + 1, current_path_sum)
# Start recursion at the top of triangle.
calculate_path_sum(0, 0, 0)
return minimum_total
The goal is to find the smallest path from the top of the triangle to the bottom. We can efficiently solve this by working backward from the bottom, building up the solution using previously calculated minimum path sums.
Here's how the algorithm would work step-by-step:
def minimum_total_path(triangle):
number_of_rows = len(triangle)
# Iterate from the second to last row to the top.
for i in range(number_of_rows - 2, -1, -1):
for j in range(len(triangle[i])):
# Find the smaller of the two numbers directly below.
smaller_path = min(triangle[i + 1][j], triangle[i + 1][j + 1])
# Add the smaller path to the current number.
triangle[i][j] += smaller_path
# The top element now contains the minimum total path sum.
return triangle[0][0]
Case | How to Handle |
---|---|
Empty triangle (triangle is null or empty) | Return 0 since there's no path or any element in the triangle |
Triangle with only one row (triangle.length == 1) | Return the single element in the row triangle[0][0] directly as the minimum path sum |
Triangle with a row containing a very large negative number | The dynamic programming solution will handle negative numbers correctly, potentially lowering the overall sum, but need to check for integer overflow if sums become too large |
Triangle with a row containing a very large positive number | Ensure that integer overflow doesn't occur when accumulating path sums, which can be mitigated using larger data types or modulo operations (if applicable given prompt constraints) |
Triangle with all elements being zero | The algorithm should correctly compute the minimum path sum as zero |
Triangle with skewed distribution (e.g., first few rows have small values, later rows have very large values) | Dynamic programming will still find the optimal path, but the skewed values could expose potential integer overflow issues, so we should watch out for those |
Maximum sized triangle (large number of rows) | Ensure the solution's space complexity remains within acceptable bounds, using dynamic programming with row optimization, which avoids storing the entire triangle's sum matrix |
Integer overflow when summing path values in the triangle | Use long data type to store intermediate sums to avoid overflow or consider using modulo arithmetic if problem constraints allow/require it |