LeetCode2558.从数量最多的堆取走礼物
LeetCode2558. 从数量最多的堆取走礼物【easy】。
题目描述
给你一个整数数组 gifts ,表示各堆礼物的数量。每一秒,你需要执行以下操作:
- 选择礼物数量最多的那一堆。
- 如果不止一堆都符合礼物数量最多,从中选择任一堆即可。
- 选中的那一堆留下平方根数量的礼物(向下取整),取走其他的礼物。
返回在 k 秒后剩下的礼物数量。
输入输出示例
示例 1:
输入:gifts = [25,64,9,4,100], k = 4
输出:29
解释:
按下述方式取走礼物:
- 在第一秒,选中最后一堆,剩下 10 个礼物。
- 接着第二秒选中第二堆礼物,剩下 8 个礼物。
- 然后选中第一堆礼物,剩下 5 个礼物。
- 最后,再次选中最后一堆礼物,剩下 3 个礼物。
最后剩下的礼物数量分别是 [5,8,9,4,3] ,所以,剩下礼物的总数量是 29 。
示例 2:
输入:gifts = [1,1,1,1], k = 4
输出:4
解释:
在本例中,不管选中哪一堆礼物,都必须剩下 1 个礼物。
也就是说,你无法获取任一堆中的礼物。
所以,剩下礼物的总数量是 4 。
提示:
- 1 <= gifts.length <= 10^3
- 1 <= gifts[i] <= 10^9
- 1 <= k <= 10^3
题目分析
①方法一很简单,每次对gifts数组进行排序,最后一位更新为取平方根后剩余的礼物数量,循环k次之后计算新gifts数组里元素之和。排序开销较大,属于以时间换空间的办法;
②方法二较方法一复杂一些,但也很容易想到。对于一堆礼物,我们每次需要找到数量最大的值,并且更新完这个值后又放回这堆礼物中,继续寻找下一个最大值,这明显可以通过维护一个最大堆来实现,根节点的值永远都是当前这堆礼物的最大值。最后,最大堆中所有礼物的数量之和就是我们要返回的答案。最大堆需要额外的空间开销,属于以空间换时间的方式。在C#中,可以直接使用PriorityQueue,因为优先队列有一个强大的特点:自动排序,可以非常简单的实现我们的需求。需要注意的是,PriorityQueue<TElement,TPriority>类出队列时,将删除优先级值最低的项,所以越大的值应该设一个越小的优先级值,我们可以使用该值的负数来作为优先级值。
最大堆性质:结点的键值都小于等于其父结点的键值。
最小堆性质:结点的键值都大于等于其父结点的键值。
满足最大堆性质的二叉堆叫做最大堆,满足最小堆性质的二叉堆叫做最小堆。
题解
方法一
1 | public long PickGifts(int[] gifts, int k) { |
方法二
1 | public long PickGifts(int[] gifts, int k) { |