题目:
你有 k 个背包。给你一个下标从 0 开始的整数数组 weights ,其中 weights[i] 是第 i 个珠子的重量。同时给你整数 k 。
请你按照如下规则将所有的珠子放进 k 个背包。
- 没有背包是空的。
- 如果第
i个珠子和第j个珠子在同一个背包里,那么下标在i到j之间的所有珠子都必须在这同一个背包中。 - 如果一个背包有下标从
i到j的所有珠子,那么这个背包的价格是weights[i] + weights[j]。
一个珠子分配方案的 分数 是所有 k 个背包的价格之和。
请你返回所有分配方案中,最大分数 与 最小分数 的 差值 为多少。
算法:
方法一:排序
思考过程:从一般到特殊,我们先考虑如何求背包价格,再求背包价格之差,然后求最大分值和最小分值,最后求最大分值和最小分值差值。以weights = [1,3,5,1], k = 2为例。
1.求背包价格,假设分为[1],[3,5,1],value1 = 1 + 1,value2 = 3 + 1。假设[1,3],[5,1],value3 = 1 + 3,value4 = 5 + 1
2.计算背包价格之差 value2 - value1 = 1 + 3, value4 - value3 = 3 + 5。可以看到计算最大最小分数差值时第0,n-个元素是被抵消了的。最大的分数只和分割点左右的数之和有关。
3.基于1、2我们求最大的分值,枚举所有的分割点,取分割点两数之后,取k - 1个最大值之和得到最大分数。同理取k - 1个最小值之和得到最小分数
func putMarbles(weights []int, k int) int64 {
n := len(weights)
values := make([]int, n - 1)
for i := 0; i < n - 1; i ++ {
values[i] = weights[i] + weights[i + 1]
}
sort.Ints(values)
min, max := 0, 0
for i := 0; i < k - 1; i ++ {
min = min + values[i]
max = max + values[len(values) - 1 - i]
}
return int64(max - min)
}