2026-02-17:最大子数组总值Ⅰ。用go语言,给定一个长度为 n 的整数数组 nums 和一个整数 k。 你需要从 nums 中挑出恰好 k 个非空的连续区间(子数组)。这些区间之间可以重叠,同一对左右端点 (l, r) 所表示的区间也可被重复选取多次。
每个区间的得分为该区间内元素的最大值减去最小值。总体得分等于所选 k 个区间得分的总和。 求能够获得的最大总体得分。
附注:这里“子数组”指数组中由若干相邻元素组成的非空区间。
1 <= n == nums.length <= 50000。
0 <= nums[i] <= 1000000000。
1 <= k <= 100000。
输入: nums = [4,2,5,1], k = 3。
输出: 12。
解释:
一种最优的方法是:
选择 nums[0..3] = [4, 2, 5, 1]。最大值为 5,最小值为 1,得到的值为 5 - 1 = 4。
选择 nums[1..3] = [2, 5, 1]。最大值为 5,最小值为 1,所以值也是 4。
选择 nums[2..3] = [5, 1]。最大值为 5,最小值为 1,所以值同样是 4。
将它们相加得到 4 + 4 + 4 = 12。
题目来自力扣3689。
解题大体过程
1. 问题分析与关键观察
- 题目要求在数组中选择 k 个非空连续子数组(区间),允许重叠和重复选择同一区间
- 每个区间的得分是「区间最大值 - 区间最小值」
- 目标:最大化 k 个区间的得分总和
关键观察:
- 对于一个固定区间,其得分只取决于区间内的最大值和最小值
- 如果某个区间包含数组的全局最大值和全局最小值,那么它的得分就是全局最大值减全局最小值,这是可能的最大单区间得分
- 由于允许重复选择区间,我们应该尽可能多地选择得分最高的那个区间
2. 寻找最优区间
- 遍历所有可能的子数组,找出得分最高的那个区间(最大值 - 最小值最大)
- 这个最优区间一定是包含某个最大值和某个最小值的区间
- 更精确地说,最优区间要么以某个最大值为右端点向左扩展包含最小值,要么以某个最小值为左端点向右扩展包含最大值
- 可以通过预处理每个位置左边的最小值和右边的最大值等信息来高效找出最优区间
3. 重复选择最优区间
- 找到得分最高的区间后,由于可以重复选择,我们应该选择这个区间 k 次
- 最大总体得分 = (最优区间得分) × k
4. 特殊情况处理
- 如果 k = 0,得分为 0(但题目规定 k ≥ 1)
- 如果数组长度为 1,任何区间得分都是 0(最大值=最小值),总体得分为 0
- 需要考虑多个区间得分相同的情况,任选一个即可
5. 示例验证(nums = [4,2,5,1], k = 3)
- 遍历所有可能的子数组:
- [4]:4-4=0
- [4,2]:4-2=2
- [4,2,5]:5-2=3
- [4,2,5,1]:5-1=4 ← 最高得分
- [2]:2-2=0
- [2,5]:5-2=3
- [2,5,1]:5-1=4
- [5]:5-5=0
- [5,1]:5-1=4
- [1]:1-1=0
- 最高得分为 4,出现多次
- 重复选择得分为 4 的区间 3 次:4 × 3 = 12
- 与题目输出一致
复杂度分析
时间复杂度
- 需要找到最优区间的得分,这可以通过一次遍历在 O(n) 时间内完成(使用单调栈或动态规划技巧)
- 因此总体时间复杂度为 O(n),其中 n 是数组长度
额外空间复杂度
- 如果使用单调栈方法,需要 O(n) 的额外空间来存储辅助数组
- 如果使用更巧妙的数学推导,可能只需要 O(1) 额外空间
- 但考虑到 n ≤ 50000,O(n) 的空间也是完全可以接受的
- 因此总的额外空间复杂度为 O(n)
Go完整代码如下:
package main
import (
"fmt"
"slices"
)
func maxTotalValue(nums []int, k int) int64 {
return int64(slices.Max(nums)-slices.Min(nums)) * int64(k)
}
func main() {
nums := []int{4, 2, 5, 1}
k := 3
result := maxTotalValue(nums, k)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def maxTotalValue(nums, k):
return (max(nums) - min(nums)) * k
def main():
nums = [4, 2, 5, 1]
k = 3
result = maxTotalValue(nums, k)
print(result)
if __name__ == "__main__":
main()
C++完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
long long maxTotalValue(const std::vector<int>& nums, int k) {
int maxVal = *std::max_element(nums.begin(), nums.end());
int minVal = *std::min_element(nums.begin(), nums.end());
return static_cast<long long>(maxVal - minVal) * k;
}
int main() {
std::vector<int> nums = {4, 2, 5, 1};
int k = 3;
long long result = maxTotalValue(nums, k);
std::cout << result << std::endl;
return 0;
}