Medium草稿★★★★★O(n) 時間 · O(1) 空間
Dynamic ProgrammingGreedy
Patterns🔲 網格・雙序列 DP🪙 貪心
尚未複習過

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

1911Maximum Alternating Subsequence Sum2-D DPMedium2-D DP

給定一個陣列 nums,子序列的交替和定義為奇數索引位置的元素之和減去偶數索引位置的元素之和(子序列自身的索引從 0 開始)。回傳最大交替子序列和。

Example:

Input: nums = [4,2,5,3] Output: 7 (子序列 [4,2,5],交替和 = 4 - 2 + 5 = 7)

Intuition

TIP

維護兩個狀態:下一個要加的(偶數位)和下一個要減的(奇數位)的最大交替和。

Approaches

1. 2D DP — O(n) / O(n)
  • Idea: dp[i][0] 表示考慮前 i 個元素,下一個要加的最大值;dp[i][1] 表示下一個要減的最大值。
  • Time: O(n)
  • Space: O(n)
class Solution {
    fun maxAlternatingSum(nums: IntArray): Long {
        val n = nums.size
        val dp = Array(n + 1) { LongArray(2) }

        for (i in 1..n) {
            dp[i][0] = maxOf(dp[i - 1][0], dp[i - 1][1] + nums[i - 1]) // 不選 or 從 odd 狀態選(加)
            dp[i][1] = maxOf(dp[i - 1][1], dp[i - 1][0] - nums[i - 1]) // 不選 or 從 even 狀態選(減)
        }
        return maxOf(dp[n][0], dp[n][1])
    }
}
⭐ 2. Space-Optimized DP — O(n) / O(1)
  • Idea: 只需兩個變數 evenodd 記錄狀態。
  • Time: O(n)
  • Space: O(1)
class Solution {
    fun maxAlternatingSum(nums: IntArray): Long {
        var even = 0L  // 下一個選的元素會被加
        var odd = 0L   // 下一個選的元素會被減

        for (num in nums) {
            val newEven = maxOf(even, odd + num)
            val newOdd = maxOf(odd, even - num)
            even = newEven
            odd = newOdd
        }
        return maxOf(even, odd)
    }
}

🔑 Takeaways