给你一个整数数组 arr,请你将该数组分隔为长度最多为 k 的一些(连续)子数组。分隔完成后,每个子数组的中的所有值都会变为该子数组中的最大值。
返回将数组分隔变换后能够得到的元素最大和。本题所用到的测试用例会确保答案是一个 32 位整数。
题目链接:https://leetcode.cn/problems/partition-array-for-maximum-sum/
# 解题思路
动态规划:
dp[i]
表示以 arr 前 i+1
(i 从 0 开始)个元素分组之后所能得到的最大数组和。
- 当
i<k
时,很明显最大和就是dp[i] = max(arr[0...i]) * (i+1)
- 当
i>=k
时,dp[i] = max(dp[j-1] + max(arr[i-j+1 ... i]) * (i-j+1)
,其中i-k < j <= i
# 代码
class Solution { | |
public int maxSumAfterPartitioning(int[] arr, int k) { | |
int n = arr.length; | |
//dp [i] 表示以 arr [i] 结尾分割的最大和 | |
int[] dp = new int[n]; | |
// 当 i < k 时,分成一组即可获得最大的和 | |
int maxVal = 0; | |
for (int i = 0; i < k; ++i) { | |
maxVal = Math.max(maxVal, arr[i]); | |
dp[i] = maxVal * (i + 1); | |
} | |
for (int i = k; i < n; ++i) { | |
maxVal = arr[i]; | |
// 枚举 k 个分割点的,获取最大和 | |
for (int j = i; j >= 0 && j > i - k; --j) { | |
maxVal = Math.max(arr[j], maxVal); | |
dp[i] = Math.max(dp[i], dp[j - 1] + (i - j + 1) * maxVal); | |
} | |
} | |
return dp[n - 1]; | |
} | |
} |