LeetCode 2171 Removing Minimum Number of Magic Beans (前缀和 推荐)

You are given an array of positive integers beans, where each integer represents the number of magic beans found in a particular magic bag.

Remove any number of beans (possibly none) from each bag such that the number of beans in each remaining non-empty bag (still containing at least one bean) is equal. Once a bean has been removed from a bag, you are not allowed to return it to any of the bags.

Return the minimum number of magic beans that you have to remove.

Example 1:

Input: beans = [4,1,6,5]
Output: 4
Explanation: 
- We remove 1 bean from the bag with only 1 bean.
  This results in the remaining bags: [4,0,6,5]
- Then we remove 2 beans from the bag with 6 beans.
  This results in the remaining bags: [4,0,4,5]
- Then we remove 1 bean from the bag with 5 beans.
  This results in the remaining bags: [4,0,4,4]
We removed a total of 1 + 2 + 1 = 4 beans to make the remaining non-empty bags have an equal number of beans.
There are no other solutions that remove 4 beans or fewer.

Example 2:

Input: beans = [2,10,3,2]
Output: 7
Explanation:
- We remove 2 beans from one of the bags with 2 beans.
  This results in the remaining bags: [0,10,3,2]
- Then we remove 2 beans from the other bag with 2 beans.
  This results in the remaining bags: [0,10,3,0]
- Then we remove 3 beans from the bag with 3 beans. 
  This results in the remaining bags: [0,10,0,0]
We removed a total of 2 + 2 + 3 = 7 beans to make the remaining non-empty bags have an equal number of beans.
There are no other solutions that removes 7 beans or fewer.

Constraints:

  • 1 <= beans.length <= 10^5
  • 1 <= beans[i] <= 10^5

题目链接:https://leetcode.com/problems/removing-minimum-number-of-magic-beans/

题目大意:每个篮子有n个物品,可任意拿出若干物品,问最少一共拿掉多少物品可以使得非空的篮子中物品数相同

题目分析:大致思想是枚举每个数字,算出以当前数字作为最终篮子中物品数量时需要拿出的总数,因数据量只有10^5,可直接用数组求出每个数字出现的频数frq,再计算前缀值和sum以及前缀个数和cnt,对于数字num,小于它的部分显然都应该被拿掉,即sum[num - 1],大于它的部分一共比它大了sum[N] - sum[num] (N为总长),若这部分的值都为num,则总和为num * (cnt[N] - cnt[num]),因此想要这部分值都为num,一共需要拿出sum[N] - sum[num] - num * (cnt[N] - cnt[num])这么多的物品,再加上小于num全部拿出的部分,我们就可以O(1)的复杂度算出以每个数字为最终个数的解,取最小即可

26ms,时间击败99.45%

class Solution {
    final int N = 100000;

    long[] frq = new long[N + 5];
    long[] sum = new long[N + 5];
    long[] cnt = new long[N + 5];
    
    public long minimumRemoval(int[] beans) {
        for (int num : beans) {
            frq[num]++;
        }
        for (int i = 1; i <= N; i++) {
            sum[i] = sum[i - 1] + i * frq[i];
            cnt[i] = cnt[i - 1] + frq[i];
        }
        long ans = Long.MAX_VALUE;
        for (int num : beans) {
            ans = Math.min(ans, magic(num));
        }
        return ans;
    }
    
    private long magic(int num) {
        return sum[num - 1] + sum[N] - sum[num] - num * (cnt[N] - cnt[num]);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值