6339. 将珠子放入背包中

233 阅读2分钟

题目:
你有 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)
}