博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Leetcode 887. Super Egg Drop
阅读量:5940 次
发布时间:2019-06-19

本文共 3843 字,大约阅读时间需要 12 分钟。

Problem:

You are given K eggs, and you have access to a building with N floors from 1 to N

Each egg is identical in function, and if an egg breaks, you cannot drop it again.

You know that there exists a floor F with 0 <= F <= N such that any egg dropped at a floor higher than F will break, and any egg dropped at or below floor F will not break.

Each move, you may take an egg (if you have an unbroken one) and drop it from any floor X (with 1 <= X <= N). 

Your goal is to know with certainty what the value of F is.

What is the minimum number of moves that you need to know with certainty what F is, regardless of the initial value of F?

 

Example 1:

Input: K = 1, N = 2Output: 2Explanation: Drop the egg from floor 1.  If it breaks, we know with certainty that F = 0.Otherwise, drop the egg from floor 2.  If it breaks, we know with certainty that F = 1.If it didn't break, then we know with certainty F = 2.Hence, we needed 2 moves in the worst case to know what F is with certainty.

Example 2:

Input: K = 2, N = 6Output: 3

Example 3:

Input: K = 3, N = 14Output: 4

 

Note:

  1. 1 <= K <= 100
  2. 1 <= N <= 10000

 

Solution:

  说道扔鸡蛋问题,就不得不提一下那个经典的dp问题。给m个鸡蛋尝试n次,最坏情况下可以在多少楼层内确定会让鸡蛋破裂的最低层数。

  对于这道题,我们可以创建一个二维数组dp,dp[i][j]表示用i个鸡蛋尝试j次可以确定的最高楼层数。这个最高楼层可以由两部分组成,假设我们在x楼扔下一个鸡蛋,它可能会破也可能不会破,如果鸡蛋破了,那么我们需要用剩下的i-1个鸡蛋和就-1次机会在x楼之下寻找这个最高楼层,即dp[i-1][j-1],若鸡蛋破了,则我们需要在x+1层之上用i个鸡蛋尝试j-1次找到那个最高楼层,即dp[i][j-1],因此可以得到状态转移方程:dp[i][j] = dp[i-1][j-1]+1+dp[i][j-1],对于i=1,dp[1][i] = i。代码部分如下:

1 class Solution { 2 public: 3     int superEggDrop(int K, int N) { 4         vector
> dp(K+1,vector
(N+1,0)); 5 for(int j = 0;j <= N;++j) 6 dp[1][j] = j; 7 for(int i = 2;i <= K;++i){ 8 for(int j = 1;j <= N;++j){ 9 dp[i][j] = dp[i-1][j-1]+1+dp[i][j-1];10 }11 }12 return dp[K][N];13 }14 };

 

  现在来看这道题有什么不同呢,现在他告诉我们最高楼层,要我们找到最小的尝试次数,即告诉我们i和dp[i][j]要我们计算j的值。和上面那题的思路类似,我们令x为测试的楼层,在这一楼层扔鸡蛋有两种情况,如果蛋碎了,则我们需要在x-1层里用i-1个鸡蛋找到最小的尝试次数,如果蛋没碎,则要在x+1到j层用i个鸡蛋找到最小尝试次数,所以max(dp[i-1][x],dp[i][j-x])即在x层扔下第一个鸡蛋的情况下,用i个鸡蛋在j层内的最小尝试次数。所以,我们需要在0-j层内找到合适的x,使得这个最小尝试次数最少,所以这就成了一个极小化极大值的问题。在这里其实我们可以观察到dp[i-1][x]是递增的,而dp[i][j-x]是递减的,所以我们在0-j内遍历x,当dp[i-1][x] == dp[i][j-x]时,可以断定此时的x即第一个鸡蛋应该扔的楼层,所以dp[i][j]就等于dp[i-1][x]+1。

  对于这个解法,其时间复杂度为O(kN2),我们可以观察到在确定x的过程中,我们通过遍历的方法寻找x,在这个地方我们其实可以通过二分法进行优化,将时间复杂度降低为O(kN*logN)。(虽然通过二分法时间复杂度降低了,但程序的运行时间却增加了,所以算法复杂度和程序运行时间真是没必然联系啊)

  由于这道题的状态转移方程只需要i-1层的数据,其空间复杂度也可以降低为O(N),感兴趣的读者可以继续优化算法。

Code:

 

1 class Solution { 2 public: 3     int superEggDrop(int K, int N) { 4         vector
> dp(K+1,vector
(N+1,0)); 5 for(int j = 0;j <= N;++j) 6 dp[1][j] = j; 7 for(int i = 2;i <= K;++i){ 8 int x = 1; 9 for(int j = 1;j <= N;++j){10 while(x < j && dp[i][j-x] > dp[i-1][x])11 x++;12 dp[i][j] = 1+dp[i][j-x];13 }14 }15 return dp[K][N];16 }17 };

 

1 class Solution { 2 public: 3     int superEggDrop(int K, int N) { 4         vector
> dp(K+1,vector
(N+1,0)); 5 for(int j = 0;j <= N;++j) 6 dp[1][j] = j; 7 for(int i = 2;i <= K;++i){ 8 for(int j = 1;j <= N;++j){ 9 int start = 1;10 int end = j;11 while(start < end){12 int pivot = start+(end-start)/2;13 if(dp[i][j-pivot] > dp[i-1][pivot])14 start = pivot+1;15 else16 end = pivot;17 }18 dp[i][j] = 1+dp[i][j-start];19 }20 }21 return dp[K][N];22 }23 };

 

转载于:https://www.cnblogs.com/haoweizh/p/10182908.html

你可能感兴趣的文章
Java修改文件夹下所有文件名
查看>>
IOS NSInvocation应用与理解
查看>>
XCode 7上传遇到ERROR ITMS-90535 Unexpected
查看>>
iOS开发拓展篇—静态库
查看>>
【Mongodb】 Replica set的主从切换测试
查看>>
第一个 mac 程序 Create-JSON-Model
查看>>
Rafy 框架 - 大批量导入实体
查看>>
为何大多数人做出来的图表只是一坨屎?
查看>>
程序员的量化交易之路(35)--Lean之DataFeed数据槽3
查看>>
Tiny4412开发板 LED灯的控制
查看>>
【目录】C#操作Excel组件Spire.XLS系列文章目录
查看>>
ORACLE关闭启动的诡异错误
查看>>
汇编语言--寄存器(cpu工作原理)
查看>>
【DataGuard】ORA-16014 and ORA-00312 Messages in Alert.log of Physical Standby
查看>>
MongoDB主从复制
查看>>
Node.js链式回调
查看>>
B/S项目结束,又是一个新的开始
查看>>
是时候对XSLT说“Goodbye”了吗?
查看>>
Android Studio(十二):打包多个发布渠道的apk文件
查看>>
android universal image loader 缓冲原理详解
查看>>