Medium草稿★★★★★O(n^2) 時間 · O(n) 空間
Dynamic ProgrammingArray
Patterns📈 線性 DP・Kadane
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

120Triangle1-D DPMedium1-D DP

給定一個三角形陣列 triangle,找出從頂部到底部的最小路徑總和。每一步只能移動到下一行的相鄰節點(即索引 ii+1)。

Example:

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

Intuition

TIP

從底部往上 DP,每個位置選擇下一行左右鄰居中較小的加上自己。

Approaches

1. Top-Down Memoization — O(n^2) / O(n^2)
  • Idea: 從頂部遞迴向下,記憶化每個 (row, col) 的最小路徑和
  • Time: O(n^2)
  • Space: O(n^2)
class Solution {
    fun minimumTotal(triangle: List<List<Int>>): Int {
        val n = triangle.size
        val memo = Array(n) { IntArray(it + 1) { Int.MAX_VALUE } }
        fun dp(row: Int, col: Int): Int {
            if (row == n) return 0
            if (memo[row][col] != Int.MAX_VALUE) return memo[row][col]
            memo[row][col] = triangle[row][col] + minOf(dp(row + 1, col), dp(row + 1, col + 1))
            return memo[row][col]
        }
        return dp(0, 0)
    }
}
⭐ 2. Bottom-Up with O(n) Space — O(n^2) / O(n)
  • Idea: 從最底行往上逐行合併,只用一維陣列記錄當前行的最小路徑和
  • Time: O(n^2)
  • Space: O(n)
class Solution {
    fun minimumTotal(triangle: List<List<Int>>): Int {
        val n = triangle.size
        val dp = triangle[n - 1].toIntArray()
        for (i in n - 2 downTo 0) {
            for (j in 0..i) {
                dp[j] = triangle[i][j] + minOf(dp[j], dp[j + 1])
            }
        }
        return dp[0]
    }
}

🔑 Takeaways