文章目录
4-11.鸡蛋掉落
思路:
这道题主要分两部分,一个是写出转移方程,另一个是优化算法。
- 只有一个鸡蛋的时候,只能从1层开始扔,一层一层扔才能保证得到F楼层。(如果从其他楼层开始扔, 如果碎了,那么无法确定F是在当前楼层还是低楼层。)
- 有多个鸡蛋的时候,第一个鸡蛋可以从任意楼层扔(j楼);
1)如果碎了,那么F楼层在比当前低的楼层中,鸡蛋个数减一,移动次数为当有k-1个鸡蛋时,j-1楼最小的移动次数+1。
2)如果没碎,那么F楼层在比当前高的楼层中,鸡蛋个数不变,移动次数为当前k个鸡蛋,N-j楼最小的移动次数+1 - 第一个鸡蛋可在某个楼层扔时,使得整体移动次数最小,找到它!
举个例子:
比如K=2,N=9
这个留着,以后画图方便时再写吧…
简单解释下代码:
lis[i][j]表示,i个鸡蛋j层楼所需最小移动次数。
二分法来找到第一个鸡蛋扔的最佳位置,如果用for循环会超时。
m代表第一个鸡蛋在哪个楼层扔,
低楼层所需的最小次数为lis[i-1][m-1];
高楼层所需的最小次数为lis[i][j-m];
当两者尽可能接近的时候,楼层最优。
两者有一个趋势,低楼层所需的最小次数是不断增加的,即一个递增序列,找到使得低楼层所需最小次数最大且小于等于高楼层所需最小次数即可。
算法的时间复杂度是:O(KNlogN)
在这里插入代码class Solution(object):
def superEggDrop(self, K, N):
"""
:type K: int
:type N: int
:rtype: int
"""
lis = [[0 for i in range(N+1)] for j in range(K)]
for i in range(K):
for j in range(1,N+1):
if i == 0:
lis[i][j] = j
elif j == 1:
lis[i][j] = 1
else:
#找分割点
lf = 1
rg = j
m = (lf + rg)>>1
while lf < rg:
if lis[i-1][m-1] < lis[i][j-m]:
lf = m+1
elif lis[i-1][m-1] > lis[i][j-m]:
rg = m
else:
break
m = (lf+rg)>>1
lis[i][j] = lis[i-1][m-1] + 1
# print lis
return lis[-1][-1]