千问 LeetCode 3077. K 个不相交子数组的最大能量值 Go实现
以下是 LeetCode 3077. K 个不相交子数组的最大能量值 的 Go 语言实现:
func maximumStrength(nums []int, k int) int64 {
n := len(nums)
// 1. 计算前缀和数组,方便快速求取子数组的和
sum := make([]int64, n+1)
for i := 1; i <= n; i++ {
sum[i] = sum[i-1] + int64(nums[i-1])
}
// 2. 定义 dp 数组:dp[i][j] 表示前 j 个元素中选出 i 个不相交子数组的最大能量值
dp := make([][]int64, k+1)
for i := 0; i <= k; i++ {
dp[i] = make([]int64, n+1)
}
// 3. 动态规划填表
for i := 1; i <= k; i++ {
// 划分 i 个子数组至少需要 i 个元素,i-1 个元素无法划分,初始化为负无穷
dp[i][i-1] = -(1 << 60)
mx := int64(-(1 << 60))
// 计算当前第 i 个子数组对应的权重 w
w := int64(k - i + 1)
if i % 2 == 0 {
w = -w
}
// j 代表当前考虑的前 j 个元素,且要保证后面有足够的元素划分剩余的子数组
for j := i; j <= n - (k - i); j++ {
// 维护前缀最大值:max(dp[i-1][L] - sum[L] * w)
val := dp[i-1][j-1] - sum[j-1] * w
if val > mx {
mx = val
}
// 状态转移:不选第 j 个元素,或者以第 j 个元素结尾作为第 i 个子数组
notTake := dp[i][j-1]
take := sum[j] * w + mx
if notTake > take {
dp[i][j] = notTake
} else {
dp[i][j] = take
}
}
}
return dp[k][n]
}
Go 语言实现注意事项:
1. 数据类型:由于子数组的和以及权重乘积可能非常大,Go 中必须使用 int64 类型来存储前缀和 sum 以及 DP 状态 dp,避免整数溢出。
2. 负无穷表示:Go 中没有内置的 Long.MIN_VALUE,可以使用 -(1 << 60) 来安全地表示一个足够小的负无穷值。
3. 核心逻辑:与 Java 版本完全一致,利用前缀和与滑动窗口最大值思想,将原本 O(n^3) 的暴力枚举优化为 O(n times k) 的时间复杂度。
