leetcode
leetcode 2251 ~ 2300
将珠子放入背包中

将珠子放入背包中

难度:

标签:

题目描述

You have k bags. You are given a 0-indexed integer array weights where weights[i] is the weight of the ith marble. You are also given the integer k.

Divide the marbles into the k bags according to the following rules:

  • No bag is empty.
  • If the ith marble and jth marble are in a bag, then all marbles with an index between the ith and jth indices should also be in that same bag.
  • If a bag consists of all the marbles with an index from i to j inclusively, then the cost of the bag is weights[i] + weights[j].

The score after distributing the marbles is the sum of the costs of all the k bags.

Return the difference between the maximum and minimum scores among marble distributions.

 

Example 1:

Input: weights = [1,3,5,1], k = 2
Output: 4
Explanation: 
The distribution [1],[3,5,1] results in the minimal score of (1+1) + (3+1) = 6. 
The distribution [1,3],[5,1], results in the maximal score of (1+3) + (5+1) = 10. 
Thus, we return their difference 10 - 6 = 4.

Example 2:

Input: weights = [1, 3], k = 2
Output: 0
Explanation: The only distribution possible is [1],[3]. 
Since both the maximal and minimal score are the same, we return 0.

 

Constraints:

  • 1 <= k <= weights.length <= 105
  • 1 <= weights[i] <= 109

代码结果

运行时间: 160 ms, 内存: 28.6 MB


// Java Stream solution
// 思路:使用Java Stream API来计算所有可能的背包价格,然后找到最大和最小价格的差值。

import java.util.Arrays;
import java.util.stream.IntStream;

public class BeadsDistributionStream {
    public int maxMinDifference(int[] weights, int k) {
        int n = weights.length;
        // 计算每个可能的背包价格
        int[] prices = IntStream.range(0, n - 1)
                .map(i -> weights[i] + weights[i + 1])
                .sorted()
                .toArray();
        int minPrice = IntStream.range(0, k - 1).map(i -> prices[i]).sum();
        int maxPrice = IntStream.range(0, k - 1).map(i -> prices[n - 2 - i]).sum();
        return maxPrice - minPrice;
    }

    public static void main(String[] args) {
        BeadsDistributionStream bds = new BeadsDistributionStream();
        int[] weights = {1, 3, 5, 1};
        int k = 2;
        System.out.println(bds.maxMinDifference(weights, k)); // 输出:4
    }
}

解释

方法:

题解的主要思路是首先计算所有相邻珠子的和,存储在一个数组中。然后将这个数组排序,以便于选出珠子组合的最大和最小值。具体步骤如下:1. 首先对于每一对相邻的珠子,计算它们的重量和,形成一个新的数组。2. 将这个新数组进行排序。3. 从排序后的数组中,为了获得最大分数,选择末尾的k-1个元素(因为这些是最大的k-1个组合),并计算它们的和。4. 同时,为了保证没有空背包,计算前k-1个元素(最小的k-1个组合)的和。5. 最终得分是最大组合和减去最小组合和。

时间复杂度:

O(n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
题解中提到对相邻珠子重量和的数组进行排序后计算最大和最小组合的和,为什么选择排序这个数组,而不是直接在未排序的数组上操作?
排序这个数组是为了方便从中快速选取最大和最小的k-1个组合。如果不进行排序,直接在未排序的数组上寻找最大和最小的k-1个组合,将需要更复杂的算法(如使用优先队列或其他选择算法),这可能会增加时间复杂度。排序后,数组的最大和最小值可以直接通过索引访问,使得操作更为简单和高效。
🦆
在计算珠子组合的和时,为什么选择最大的k-1个元素和最小的k-1个元素,这样的选择依据是什么?
选择最大的k-1个元素和最小的k-1个元素是为了最大化背包的价格差异,从而最大化整体分数。最大的k-1个组合提供了可能的最高价格,而最小的k-1个组合提供了可能的最低价格。通过计算这两者的差值,可以确保所有背包中的珠子组合都被考虑到,同时最大化了分数。这种方法确保了在满足所有背包都不为空的前提下,分数被最大化。
🦆
题解中提到的算法是否考虑了所有珠子必须被分配到背包的约束,尤其是在珠子数量不是k的整数倍时的情形?
题解中的算法确实没有明确说明如何处理珠子数量不是k的整数倍的情形。算法假设了每个背包可以放置不同数量的珠子,只要这些珠子是连续的。然而,确实需要更详细的逻辑来确保在珠子数量不均等时,每个背包至少包含一个珠子,特别是处理边界情况,例如当珠子数量少于背包数量时。这可能需要调整算法以确保所有珠子都被合理地分配,避免有空背包的情况发生。

相关问题