Leetcode 887. Super Egg Drop

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 = 2
Output: 2
Explanation: 
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 = 6
Output: 3

Example 3:

Input: K = 3, N = 14
Output: 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<vector<int>> dp(K+1,vector<int>(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<vector<int>> dp(K+1,vector<int>(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<vector<int>> dp(K+1,vector<int>(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                     else
16                         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

时间: 2024-10-07 23:24:16

Leetcode 887. Super Egg Drop的相关文章

Super Egg Drop

一道陈题. 100 层楼 2 个玻璃球 起因是窥室友手机屏, 看到他群里有人问一个经典问题. 两个一模一样的玻璃球, 两个玻璃球如果从一定高度掉落到地上会被摔碎, 如果在这个高度以下往下扔怎么都不会碎, 现在已知这个恰巧摔碎的高度范围在 1 层楼到 100 层楼之间, 如何用最少的试验次数, 用这两个玻璃球测试出玻璃球恰好摔碎的楼高呢?1 当只剩 1 个球时, 只能一层一层往上测试. 第 1 个球的任务是减少第 2 个球所需测试的次数. 直观上讲, 第 1 个球测试点的间隔要越来越小, 这样第

LeetCode887 - Super Egg Drop - Hard (Python)

这是labuladong的文章总结. 这是一题经典的DP问题,DP的框架为首先思考这个问题有什么状态,有哪些选择,最后根据情况穷举所有可行解. 这题的状态即为当前拥有的鸡蛋数k以及当前所在的楼层数n.选择是我们选择去哪一层楼扔鸡蛋.由状态和选择我们可以得到相对应的转移方程(因为有两个状态,鸡蛋数以及楼层数,所以我们可以考虑用二维的数组): dp[k][i] = min(dp[k][i], max(dp[k-1][i-1], dp[k][n-i]) 在i层楼扔鸡蛋,鸡蛋可能碎也可能不碎(状态转移方

【Leetcode】Super Ugly Number

题目链接:https://leetcode.com/problems/super-ugly-number/ 题目: Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. For example, [1, 2, 4, 7, 8, 13

LeetCode(313):Super Ugly Number

Super Ugly Number: Write a program to find the nth super ugly number.Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequenc

[LeetCode] 887. 鸡蛋掉落

这道题好变态...... import java.util.Arrays; public class Solution { public int superEggDrop(int K, int N) { // dp[i][j]:一共有 i 层楼梯的情况下,使用 j 个鸡蛋的最少仍的次数 int[][] dp = new int[N + 1][K + 1]; // 初始化 for (int i = 0; i <= N; i++) { Arrays.fill(dp[i], i); } for (in

第十五周 Leetcode 517. Super Washing Machines(HARD) 贪心

Leetcode517 很有趣的一道题 由于每一步可以任选某些数字对它们进行转移,所以实际上是在求最优解中的最复杂转移数. 那么我们考虑,到底哪一个位置要经过的流量最大呢? 枚举每个位置,考虑它左边的整体需求和右边的整体需求,如果两边都需要流入,则流量相加: 如果一边需要流入,一边需要流出,则取绝对值的最大值. 复杂度O(n) class Solution { public: int findMinMoves(vector<int>& machines) { int len = mac

【LeetCode】动态规划(下篇共39题)

[600] Non-negative Integers without Consecutive Ones [629] K Inverse Pairs Array [638] Shopping Offers [639] Decode Ways II [646] Maximum Length of Pair Chain [647] Palindromic Substrings [650] 2 Keys Keyboard [651] 4 Keys Keyboard [656] Coin Path [6

【LeetCode】动态规划(下篇)

[600] Non-negative Integers without Consecutive Ones [629] K Inverse Pairs Array [638] Shopping Offers [639] Decode Ways II [646] Maximum Length of Pair Chain [647] Palindromic Substrings [650] 2 Keys Keyboard [651] 4 Keys Keyboard [656] Coin Path [6

【LeetCode】数学(共106题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [2]Add Two Numbers [7]Reverse Integer [8]String to Integer (atoi) [9]Palindrome Number [12]Integer to Roman [13]Roman to Integer [29]Divide Two Integers [43]Multiply Strings [50]Pow(x,