|
| 1 | +# Min Path Sum in Triangle |
| 2 | + |
| 3 | +Given an array, triangle, return the minimum path sum from top to bottom. You may move to an adjacent number in the row |
| 4 | +below at each step. More formally, if you are at index i in the current row, you may move to either index i or index |
| 5 | +i+1 in the next row. |
| 6 | + |
| 7 | +## Constraints |
| 8 | + |
| 9 | +- 1 <= triangle.length <= 200 |
| 10 | +- triangle[0].length == 1 |
| 11 | +- triangle[i].length == triangle[i - 1].length + 1 |
| 12 | +- -10^4 <= triangle[i][j] <= 10^4 |
| 13 | + |
| 14 | +## Solution |
| 15 | + |
| 16 | +The goal is to find the minimum path sum from the top of a triangular array to its base, moving at each step to one of |
| 17 | +the two adjacent numbers in the next row. A greedy choice at the top may fail because a small value early on can lead to |
| 18 | +a costly region later, and plain recursion is inefficient since it revisits the same subproblems many times. This |
| 19 | +problem is a natural fit for dynamic programming: |
| 20 | +the best path through a cell depends only on the best paths beneath it (optimal substructure), and many different routes |
| 21 | +share the same suffixes (overlapping subproblems). |
| 22 | + |
| 23 | +To solve it efficiently, we take a bottom-up approach. We begin with the last row, whose values represent the known |
| 24 | +final costs of any path ending there. From there, we move upward one row at a time. For each number, we determine its |
| 25 | +minimum path cost by adding its own value to the smaller of the two pre-calculated path costs in the row directly below |
| 26 | +it. This process effectively “folds” the triangle’s path information upward, continuously updating each row with the |
| 27 | +optimal costs from the level below. By this process’s peak, the single top number has been transformed to hold the total |
| 28 | +of the most efficient path through the entire structure. |
| 29 | + |
| 30 | +The following steps can be performed to implement the algorithm above: |
| 31 | + |
| 32 | +1. First, we create a one-dimensional list, `dp`, to store our minimum path sums. This list is initialized as a copy of |
| 33 | + the last row of the triangle, i.e., triangle[-1]. This serves as our base case, because the minimum path cost from |
| 34 | + any number in the last row to the bottom is simply its own value. |
| 35 | +2. Next, we iterate from the second-to-last row (rowIdx = len(triangle) - 2) of the triangle and move upward, one row at |
| 36 | + a time, until we reach the top (rowIdx = 0). This bottom-up order ensures that when we process a row, the optimal |
| 37 | + path costs for the row below it are already calculated and stored in the dp list. |
| 38 | + - We create a nested loop inside the main loop that iterates through each number in the current row. |
| 39 | + - For the current number, triangle[rowIdx][colIdx], we calculate its minimum path sum using: |
| 40 | + - min(dp[colIdx], dp[colIdx + 1]) |
| 41 | + - After finding the minimum of the two, we add it to triangle[rowIdx][colIdx]. |
| 42 | + - Finally, we update the dp list at the current position with this new, smaller total. |
| 43 | + |
| 44 | +3. After the loops complete, the dp list contains the fully collapsed path information. The final answer for the entire |
| 45 | + journey, from the top to the bottom, is now the list’s first element, dp[0]. |
| 46 | + |
| 47 | +### Time Complexity |
| 48 | + |
| 49 | +The time complexity is O(n^2) where n is the number of rows in the triangle. This is because the algorithm processes |
| 50 | +each element exactly once, and the total number of elements in a triangle with n rows is about n * (n + 1)/2, which |
| 51 | +grows quadratically. |
| 52 | + |
| 53 | +### Space Complexity |
| 54 | + |
| 55 | +The space complexity is O(n) since we only maintain a single working array `dp` with one entry per row. |
0 commit comments