力扣 2517

文章讨论了在优化问题中使用min-max和max-min策略,特别是在寻找最大甜蜜度的问题上,通过二分法来平衡礼盒的均衡性。解题的关键在于将遍历问题转化为二分判断问题,通过调整上下界找到最大值。同时提到了在二分法实现中的细节,如防止整型溢出和区间处理,以及避免死循环的方法。
摘要由CSDN通过智能技术生成

题目介绍 & 无端联想

一句话说:
min-max是为了压制优化目标中表现最突出的成分,降低最恶劣情况的影响
max-min为了提升优化目标中表现最差的成分,增加整体解决方案均衡性

本题求最大甜蜜度,属于最大最小问题,从礼盒商的角度来说应是为了增加礼盒均衡性,避免有的用户买到觉得自己亏了。

此类题目常见的形式是:给出一个序列,从 n 个里面选 k 个,对这个组合求某值,再从全部组合的角度对该某值求最大最小。

由于是求最值,解法上多少有点逆向思维,正向思维是求出每一种组合的值,比较得出最大的。逆向思维是推导这个值的上下限,二分夹出来这个值。由一个遍历问题,转化为一个二分判断是否成立的问题。

要取得最大的甜蜜值,理论上的上限,是最大价格和最小价格的绝对差。理论上的下限,是两个相同的价格。根据二分法的需要,首先判断中间值 mid 是否成立,即当最大甜蜜度 = mid 时,能否找出 k 个差价都大于 mid。如果找到了 >= k 个差价,那么提升下限,找更大的甜蜜度;如果只找到了 < k 个差价,那么减低上限,找更小的甜蜜度。

这里面有一点小小的转换,如果超过 k 个差价大于当前的甜蜜度,就认为还有更大的甜蜜度可以成立。

类似题目

LC 2064。这个是求最小值,也就是压制可能取得最大商品数的店铺。用上面的思路和套路,很快做出来了

一开始时间损耗极大,因为我翻了个错误,懒省事用逐个减的方式看 sum 里面有几个 k,其实用除法运算就一步到位了。

二分法

二分法老是出问题。

  1. 首先理想状态下,应该是 left == right 退出循环。因此循环的条件是 left < right,潜台词认为这是一个左闭右开区间 [left, right)。
  2. 其次在相加 left 和 right 的时候,为了防止整型溢出,可以写成 mid = left + (right - left) / 2,或用 long long。
  3. 接着 (left+right+1) >> 1 这种向高位取整的做法,退出循环的条件依然是 left == right,但得出的结果 left 会比正确答案小 1。
  4. 最后,需要保证上限 right = mid -1,具体原因参见第三篇参考文献。
while (left < right) {
	int mid = (left+right+1) >> 1;
    if (check(price, k, mid)) {
    	left = mid;
    } else {
        right = mid - 1;
    }
}

因为 mid 已经 check 了一次,如果不能从搜索区间里面踢出去,还能对他重复 check 的话,就不保证不会死循环了,所以新的界限不能包含 mid。

记住当前是什么区间,如果是左闭右开区间,right = mid 的时候,区间内天然已经没有了 mid 这个值,不需要额外加一减一,如果是左闭右闭区间,left 和 right 都需要加一减一才能排除 mid 这个元素。

参考文献

如何理解最大化最小值问题和最小化最大值问题
二分解决最小最大问题
我作了首诗,保你闭着眼睛也能写对二分查找

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值