LC 2141. 同时运行 N 台电脑的最长时间
https://leetcode-cn.com/problems/maximum-running-time-of-n-computers/
大概猜想到是二分查找,但总是觉得有某些情况没有考虑到:一个电池在中途挪去到另外一个地方充电,这个问题怎么解决呢?
其实这个放置如果画出来的话,可能就容易理解了。比如这个 链接 里面给出的图片
- 假设我们二分查找是进行 `check(k)`
- 虽然红色进行了迁移,但是如果把红色挪回来的话,还是可以看红色最多使用 k 个
- 而对于少于k个的电池,在任何时候任何地方都可以被使用
- 所以最终可用的总电量是 `sum((min(x, k) for x in batteries))`
- 然后就是看这些总电量,是否可以支撑n个电脑。
这样的话代码就很好写了。
class Solution:
def maxRunTime(self, n: int, batteries: List[int]) -> int:
batteries.sort(reverse = True)
def check(k):
tt = 0
for x in batteries:
tt += min(x, k)
return tt >= n * k
s, e = 0, sum(batteries)
while s <= e:
m = (s + e) // 2
if check(m):
s = m + 1
else:
e = m - 1
return e
然后第一名还有个更好的方案,其实也可以通过上面这个图片推导过来:
- 如果红色电池特别长超过平均值,那么其实红色电池不会瓶颈,所以我们可以丢弃它。
- 当剩余的电池电量刚好都差不多的时候,并且最长的电池没有超过平均值时,那么此时的平均值就是极限。
class Solution:
def maxRunTime(self, n: int, batteries: List[int]) -> int:
batteries.sort(reverse = True)
tt = sum(batteries)
avg = 0
for x in batteries:
avg = tt // n
if x > avg:
n -= 1
tt -= x
else:
break
return avg
一旦画出上面这幅图,从另外一个视角来分析问题,有时候问题就会迎刃而解。而能否画出这幅图,则要看是否有着深入的insight, 这就是水平了。