给定一个 正整数 数组 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 个魔法豆更少的方案。
提示:
public long minimumRemoval(int[] beans) {
Arrays.sort(beans);
int total = 0;
for (int bean : beans) {
total+=bean;//求和
}
long sum = -1;//求出剩余的豆子的最大总和
for (int i = 0; i < beans.length; i++) {
sum = Math.max(sum,(long) (beans.length-i)*beans[i]);
}
return total-max;//返回需要拿出豆子的最小数量。
}
时间复杂度:O(f(x))=nlogn
核心语句执行次数:f(x) = nlogn(排序)+n(查找sum最大值)
空间复杂度:O(1)
根据提示,我们可以知道数组中元素的最大值不超过10^5,所以我们完全可以用hash来代替排序,进一步降低时间复杂度
hash之后,下标i就是原来的数组里面的值。
顺序即原始下标,就是hash数组的前缀和。用变量count记录。
public long minimumRemoval(int[] beans) {
int [] hash = new int[100001];
long total = 0;
for (int bean : beans) {
hash[bean]++;
total+=bean;
}
long sum = -1;
int count = 0;
for (int i = 1; i < 100001; i++) {
if(hash[i]!=0){
sum = Math.max(sum,(long) (beans.length-count)*i);
count+=hash[i];
}
}
return total-max;
}
时间复杂度:O(maxVal)在这里近似O(n)
空间复杂度:O(maxVal)在本题近似O(n)
运行结果:
qq群:136156434