最大平均值和的分組 | 動態規劃
阿新 • • 發佈:2022-11-29
題目大意:
將給定的陣列 nums 分成 k 個相鄰的非空子陣列,使得由每個子陣列內的平均值的總和最大化。
資料範圍:
1 <= nums.length <= 100
1 <= nums[i] <= 10^4
1 <= k <= nums.length
思路分析:
直接列舉每種劃分方案,最壞情況下共有C(100, 50)種組合,無法暴力計算。
拆分子問題,可以發現如果先解決將子陣列劃分為 k-1 段的最大平均和,合併剩餘部分為一段,則原問題答案為所有子問題解中的最優解。
從自頂向下的角度來看,結論是顯然的:將給定的陣列 nums 分成 k 個相鄰的非空子陣列,必然存在某個間斷點 s 使得 [s, n-1]為一段,而 average(nums[s:n]) + subproblem(nums[: s], k-1) 是最大的。
因而問題轉化為求解新的子問題:將給定的陣列 nums[: s] 分成 k-1 個相鄰的非空子陣列,使得由每個子陣列內的平均值的總和最大化。
實際可以採用自下而上的合併方式求解。
AC程式碼:
class Solution: def largestSumOfAverages(self, nums: List[int], k: int) -> float: n = len(nums) # dp[i][j] nums[:i] 劃分j段 平均和 dp = [[0]*(k+1) for _ in range(n)] for i in range(n): dp[i][1] = sum(nums[:i+1]) / (i+1) for i in range(n): for j in range(2, min(i+1, k)+1): # 注意上下界 for s in range(i): dp[i][j] = max(dp[i][j], dp[s][j-1]+sum(nums[s+1:i+1])/(i-s)) # [s+1:i+1]區間內總和可以預處理 return dp[n-1][k]
(完)