LeetCode(力扣) 1648. 销售价值减少的颜色球,完美结合二分算法和贪心算法

本文介绍了如何利用二分查找和贪心算法解决LeetCode 1648题——销售价值减少的颜色球。通过分析题目,作者发现可以设置一个阈值,然后寻找满足条件的阈值,从而简化问题。通过二分查找找到阈值后,使用等差数列公式计算总价值。作者强调了算法的融合与数学知识在编程中的应用,鼓励读者拓宽思维并深入学习算法。
摘要由CSDN通过智能技术生成

一个二分查找算法和贪心算法结合的场景

之所以写这个,是因为我前两周在参加 LeetCode 周赛的时候,碰到了一个这样题,题目链接如下:
1648. 销售价值减少的颜色球

1648. 销售价值减少的颜色球

你有一些球的库存 inventory ,里面包含着不同颜色的球。一个顾客想要 任意颜色 总数为 orders 的球。

这位顾客有一种特殊的方式衡量球的价值:每个球的价值是目前剩下的 同色球 的数目。比方说还剩下 6 个黄球,那么顾客买第一个黄球的时候该黄球的价值为 6 。这笔交易以后,只剩下 5 个黄球了,所以下一个黄球的价值为 5 (也就是球的价值随着顾客购买同色球是递减的)。

给你整数数组 inventory ,其中 inventory[i] 表示第 i 种颜色球一开始的数目。同时给你整数 orders ,表示顾客总共想买的球数目。你可以按照 任意顺序 卖球。

请你返回卖了 orders 个球以后 最大 总价值之和。由于答案可能会很大,请你返回答案对 10 ** 9 + 7 取余数 的结果。

示例 1:
alt test

输入:inventory = [2,5], orders = 4

输出:14

解释:卖 1 个第一种颜色的球(价值为 2 ),卖 3 个第二种颜色的球(价值为 5 + 4 + 3)。

最大总和为 2 + 5 + 4 + 3 = 14 。

提示

  • 1 <= inventory.length <= 10 ** 5
  • 1 <= inventory[i] <= 10 ** 9
  • 1 <= orders <= min(sum(inventory[i]), 10 ** 9)

分析

刚开始我完全没有意识到有二分查找的思想,就是想着用一个优先队列,然后每次取出一个元素,加上当前值,把当前值减一,然后再把当前值放入优先队列。

没过几分钟,程序就写完了,但是呢提交后显示运行超时了,我就想着去优化程序。于是我又读了下题,看看是不是我漏了啥重要条件,结果读了几遍发现这道题就是贪心的思想啊,不可能错的呀,但是结果就是超时了。。。

于是周赛结束后我特意去查了下大神写的代码,真的是让我惊呆了,是贪心的思想没错,但是时二分和贪心进行结合。

这个题想法很简单,设置一个 sum 变量,sum 每次加上数组中的最大值,然后将当前值减去 1,直到此过程重复 orders 步骤。

然后为啥用优先队列会超时呢?其实优先队列的底层就是堆,每次取出元素,加入元素都需要对堆进行调整,调整的时间复杂度是 O(logn),其中 n 是优先队列的长度,然后需要进行 orders 操作,所以总的时间复杂度就是 O(Nlogn), 其中 Nordersn 是数组长度。

而这道题的话,orders 会取到 10 ** 9,所以自然而然就会超时了。

那么应该如何解决呢?

解决思路

既然单独使用优先队列解决不了问题,那我们就换个思路进行思考。因为每次都要取数组中的最大值,然后减去 1, 所以最后呢数组中的元素肯定是小于等于某一个阈值的,这个我想你肯定是能够理解的。

那这个阈值能不能求出来呢?如果能求出来的话,那问题是不是就容易解决了呢?你想啊,如果现在我们已经求出了这个阈值,那么是不是就知道了数组中的每个元素被减了多少次,进而累加求和不就得到结果了嘛。

好,现在问题已经变成了如何求解阈值了,这个如何求解呢?我们假定阈值为 threshold,那么它满足啥条件呢?

∑ a i > t h r e s h o l d a i − t h r e s h o l d < =  orders  < ∑ a i > t h r e s h o l d a i  - threshold  + 1 \sum_{a_{i}>t h r e s h o l d} a_{i}-t h r e s h o l d<=\text { orders }<\sum_{a_{i}>t h r e s h o l d} a_{i} \text { - threshold }+1 ai>thresholda

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值