面试笔试高频编程题(二)---鸡蛋掉落问题

 鸡蛋掉落

你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N  共有 N 层楼的建筑。

每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。

你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。

每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层

 X 扔下(满足 1 <= X <= N)。

你的目标是确切地知道 F 的值是多少。

无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?

示例 1:输入:K = 1, N = 2 输出:2 解释: 鸡蛋从 1 楼掉落。如果它碎了,我们肯定知道 F = 0 。 否则,鸡蛋从 2 楼掉落。如果它碎了,我们肯定知道 F = 1 。 如果它没碎,那么我们肯定知道 F = 2 。 因此,在最坏的情况下我们需要移动 2 次以确定 F 是多少。

示例 2:输入:K = 2, N = 6 输出:3

示例 3:输入:K = 3, N = 14 输出:4

 

解法一:我们需要求一个最优策略使得扔的次数最小。用dp[n][k]表示k个鸡蛋测n层扔的最少次数,如果i层的时候鸡蛋碎了,则剩下的k-1个鸡蛋用来测1到i层,也就是dp[n][k]=dp[i-1][k-1]+1;如果没碎,则dp[n][k]=dp[n-i][k] + 1。综上,在第i层扔,

dp[n][k] = min(max(dp[i-1][k-1], dp[n-i][k]) + 1)  (1 <= i <= n)

解法二:换个思路,k个鸡蛋m次可以测多少层,也可以这样理解,我有K个鸡蛋,N层楼,等鸡蛋扔完的时候确定N层楼所用的最少次数。dp[k][m]表示k个鸡蛋在m步内可以测出的楼层数。那么问题转化为当k<=K时,找一个最小的m,使得dp[k][m]<=N。

求解dp[k][m]的策略:假设有k个鸡蛋第m步时,在第X层扔鸡蛋,这时候要么鸡蛋碎了,要么没碎。

如果没碎,我们就往更高层扔,那么确定X+dp[k][m-1]层楼的结果;

如果碎了,我们会往更底层扔,那么确定Y+dp[k-1][m-1]层的结果;(假设第X层上有Y层)

因此,这次扔鸡蛋,我们最多能测出{dp[k-1][m-1](摔碎时能确定的层数)+dp[k][m-1](没摔碎时能确定的层数)+1(本层)}层的结果。

另外,一个鸡蛋一次只能测一层,没有鸡蛋一层都测不出来。

dp[k][0]=0

dp[1][m]=m

dp[k][m]=dp[k-1][m-1] + dp[k][m-1] + 1

解法二代码如下:

def egg(K, N):
    dp = [[0 for _ in range(N+1)] for _ in range(K+1)]
    for i in range(1, K+1):
        for j in range(1, N+1):  # 一个鸡蛋最多能扔 N 次
            dp[i][j] = dp[i-1][j-1] + dp[i][j-1] + 1
            if dp[K][j] >= N:      # 鸡蛋扔完了,确定的楼层数超过了N,此时的次数为最少的次数
                return j
    return 0

你可能感兴趣的:(编程题)