题目:
Koko loves to eat bananas. There are
n
piles of bananas, theith
pile haspiles[i]
bananas. The guards have gone and will come back inh
hours.Koko can decide her bananas-per-hour eating speed of
k
. Each hour, she chooses some pile of bananas and eatsk
bananas from that pile. If the pile has less thank
bananas, she eats all of them instead and will not eat any more bananas during this hour.Koko likes to eat slowly but still wants to finish eating all the bananas before the guards return.
Return the minimum integer
k
such that she can eat all the bananas withinh
hours.
这道题主要有几个限制:
piles.length <= h
,也就是说 koko 一定能吃完所有 pile 的香蕉换言之,koko 每小时需要尽可能少吃香蕉,并且保证在 h 小时内吃完所有香蕉,这道题的暴力解为:
class Solution:
def minEatingSpeed(self, piles: List[int], h: int) -> int:
speed = 1
def hour_needed_to_eat():
total_hour_needed = 0
for pile in piles:
total_hour_needed += math.ceil(pile / speed)
if total_hour_needed > h:
return False
return total_hour_needed <= h
while True:
if hour_needed_to_eat():
return speed
speed += 1
也就是让 koko 从每小时 1 根香蕉开始吃起,一直吃到正好在 h 小时内可以吃完香蕉的速度就返回
尽管循环的条件是 while True
,不过已经得知 piles.length <= h
,所以香蕉的吃速上限为 max(piles)
,换言之,这道题可以理解成,在
[
1
,
2
,
3
,
.
.
.
,
m
a
x
(
p
i
l
e
s
)
]
[1, 2, 3, ..., max(piles)]
[1,2,3,...,max(piles)] 这样一个有序数组内,找到一个特定的解,所以暴力解的空间复杂度为
O
(
1
)
O(1)
O(1),时间复杂度为
O
(
m
a
x
(
p
i
l
e
s
)
×
n
)
O(max(piles) \times n)
O(max(piles)×n),其中
n
n
n 为数组的长度。
另外,看到 在一个有序数组中找到一个特定的解 这样的 pattern,大概是能够比较模糊的猜测出,这道题是一道 binary search,这道题的要求就是在 [ 1 , 2 , 3 , . . . , m a x ( p i l e s ) ] [1, 2, 3, ..., max(piles)] [1,2,3,...,max(piles)] 中找到一个最小的数字,使得 ∑ i = 1 m a x ( p i l e s ) m a t h . c e i l ( p i l e i ) \sum_{i=1}^{max(piles)} math.ceil(\frac{pile}{i}) ∑i=1max(piles)math.ceil(ipile) 趋近于给定的 h h h
将暴力解的写法稍微改动一下,变成 binary search:
class Solution:
def minEatingSpeed(self, piles: List[int], h: int) -> int:
l, r = 1, max(piles)
res = r
def hour_needed_to_eat(k):
total_hour_needed = 0
for pile in piles:
total_hour_needed += math.ceil(pile / k)
return total_hour_needed
while l <= r:
m = (l + r) // 2
hours_needed = hour_needed_to_eat(m)
if hours_needed <= h:
r = m - 1
res = m
else:
l = m + 1
return res
因为使用了二分算法,这道题的时间复杂度为 O ( n × l o g ( m a x ( p i l e s ) ) ) O(n \times log(max(piles))) O(n×log(max(piles)))