题目:
给定一个 正整数 数组 beans
,其中每个整数表示一个袋子里装的魔法豆的数目。
请你从每个袋子中 拿出 一些豆子(也可以 不拿出),使得剩下的 非空 袋子中(即 至少还有一颗 魔法豆的袋子)魔法豆的数目 相等。一旦把魔法豆从袋子中取出,你不能再将它放到任何袋子中。
请返回你需要拿出魔法豆的 最少数目。
示例 1:
输入:beans = [4,1,6,5] 输出:4 解释: - 我们从有 1 个魔法豆的袋子中拿出 1 颗魔法豆。 剩下袋子中魔法豆的数目为:[4,0,6,5] - 然后我们从有 6 个魔法豆的袋子中拿出 2 个魔法豆。 剩下袋子中魔法豆的数目为:[4,0,4,5] - 然后我们从有 5 个魔法豆的袋子中拿出 1 个魔法豆。 剩下袋子中魔法豆的数目为:[4,0,4,4] 总共拿出了 1 + 2 + 1 = 4 个魔法豆,剩下非空袋子中魔法豆的数目相等。 没有比取出 4 个魔法豆更少的方案。
示例 2:
输入:beans = [2,10,3,2] 输出:7 解释: - 我们从有 2 个魔法豆的其中一个袋子中拿出 2 个魔法豆。 剩下袋子中魔法豆的数目为:[0,10,3,2] - 然后我们从另一个有 2 个魔法豆的袋子中拿出 2 个魔法豆。 剩下袋子中魔法豆的数目为:[0,10,3,0] - 然后我们从有 3 个魔法豆的袋子中拿出 3 个魔法豆。 剩下袋子中魔法豆的数目为:[0,10,0,0] 总共拿出了 2 + 2 + 3 = 7 个魔法豆,剩下非空袋子中魔法豆的数目相等。 没有比取出 7 个魔法豆更少的方案。
提示:
1 <= beans.length <= 105
1 <= beans[i] <= 105
解题:
-
排序: 首先,我们对数组
beans
进行排序。排序是必要的,因为我们希望按照升序检查各个袋子中的魔法豆数目,以确定在使所有非空袋子中的魔法豆数目相等的过程中需要移除多少魔法豆。 -
累加总数: 然后,我们遍历数组
beans
,并计算所有袋子中的魔法豆总数。这一步是为了让我们知道总共有多少魔法豆,从而在后续步骤中计算需要移除的魔法豆数量。 -
查找最小移除数目: 接下来,初始化一个变量来记录最少需要移除的魔法豆数目,我们假设开始时为长整型的最大值。然后,我们再次遍历
beans
数组,对于数组中的每个元素(在这种情况下,每个元素代表排序后的袋子中魔法豆的数量),我们计算在假设该袋子后的所有袋子都要有相同数量的魔法豆情况下(即该数量等于当前元素),需要移除的魔法豆数目。这可以通过从总魔法豆数中减去乘以剩余袋子数(包括当前袋子)的当前魔法豆数来实现。 -
更新最小移除数目: 在每次迭代中,我们比较并更新记录的最小移除魔法豆数目。计算方式为当前所有魔法豆数目减去剩下的(紧随其后的)袋子数乘以当前袋子的魔法豆数目。
-
返回结果: 当遍历完成后,记录的最小移除数目即为结果。
代码:
class Solution {
public long minimumRemoval(int[] beans) {
Arrays.sort(beans);
long totalBeans = 0;
for (int bean : beans) {
totalBeans += bean;
}
long minRemovals = Long.MAX_VALUE;
long removalsTillNow = 0;
int n = beans.length;
for (int i = 0; i < n; i++) {
// 当前考虑的豆子数量与剩余的袋子相乘得到的应该保留的总豆子数量,从所有豆子中减去这个数量得到移除的数量
long currentRemovals = totalBeans - (long) (beans[i]) * (n - i);
// 更新最小移除数
minRemovals = Math.min(minRemovals, currentRemovals);
}
return minRemovals;
}
}
知识点解析:
-
数组排序 (
Arrays.sort
): 这是Java中使用的标准排序方法,用于对数组进行排序。在这段代码中,我们使用了Arrays.sort(beans)
来按升序排列给定的魔法豆数组。 -
增强型for循环 (
for (int bean : beans)
): Java的增强型for循环用于迭代数组或集合中的每个元素。在这里,它被用来遍历魔法豆数组,并计算总的魔法豆数目。 -
使用长整型变量 (
long
): 由于可能会有大量的魔法豆需要处理,因此这里使用了long
类型的变量来存储可能超过int
范围的数值。 -
Long.MAX_VALUE: 这是
long
类型变量能存储的最大值。它被用作初始化移除魔法豆的最小数量,为了在比较过程中能找到实际的最小值。 -
Math.min 方法: 这个方法用来找到两个数中的最小值。在这里,它用来更新并寻找可能的最小移除魔法豆的数目。
-
简单数学计算 (
totalBeans - (long) (beans[i]) * (n - i)
): 这个表达式被用来计算如果使所有非空袋子的魔法豆数目都等于当前袋子中的魔法豆数目时,需要从总数中移除多少魔法豆。
知识点 | 描述 | 应用 |
---|---|---|
Arrays.sort |
对数组进行排序。 | 对魔法豆的数组按数量升序排列。 |
增强型for循环 | 用于遍历数组或集合元素。 | 遍历魔法豆数组计算总数。 |
long 类型变量 |
存储大范围整数。 | 存储可能的大量魔法豆总数。 |
Long.MAX_VALUE |
long 类型的最大值。 |
初始化最小移除魔法豆数目的比较基准。 |
Math.min 方法 |
返回两个数中的最小值。 | 更新最小移除魔法豆数目。 |