题目:鸡蛋掉落
问题描述:
你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑。 每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。 你知道存在楼层 F ,满足 0 ⇐ F ⇐ N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。 每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 1 ⇐ X ⇐ N)。 你的目标是确切地知道 F 的值是多少。 无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?
解决思路:
本题常规的解决思路即是:确定第一个鸡蛋扔下的楼层数,然后根据结果判断接下来的扔鸡蛋策略。这种解决思路的难点也就在于如何确定第一个鸡蛋扔下的楼层数。于是我们可以转换思考方向:给你K个鸡蛋并且固定你的移动次数,那么你最多能够确定几层楼的扔鸡蛋情况呢。 在这种思考方向下,我们很轻易地就能确定: superEggDrop()中循环退出的条件:能够确定的楼层数要大于或等于N;getLayers()递归退出的条件:当前的移动次数或者鸡蛋数为1。 在getLayers()中,无论鸡蛋从该层扔下碎没碎,移动次数都需要减1,原因在于扔鸡蛋是需要耗费移动次数的,换言之即是我们扔了鸡蛋之后就需要移动一次以判断下一次扔鸡蛋的情况;并且在扔鸡蛋的过程中:如果鸡蛋从该层扔下碎了,则鸡蛋数也需要减1,如果没碎,那么能够确定的楼层数就需要加1。
解决代码:
class Solution {
public int superEggDrop(int K, int N) {
int moves = 1;
while(getLayers(moves, K) < N){
++moves;
}
return moves;
}
/**
* 指定的鸡蛋数在指定的移动次数下最多能够确定多少层的扔鸡蛋情况
* @param moves:移动次数
* @param eggNum:鸡蛋数
* @return:能确定扔鸡蛋情况的楼层数
*/
public int getLayers(int moves, int eggNum){
if(moves == 1 || eggNum == 1){
return moves;
}
return (getLayers(moves-1, eggNum) + 1) + getLayers(moves-1, eggNum-1);
}
}