算法思想一:扔棋子方法凑够楼层(逆向思维)
解题思路:
1、初始化扔棋子的次数 t = 1
2、不断的给 t 赋值(增加),直到给出的 t 可以测出楼层 n;其中为计算可测出最高楼层函数
1、当t = 1时,最多可以测出 2 层楼,即 t+1;当k = 1时,(假设 t = 2)则可以测出3层楼,即 t + 1
2、有 t 次机会,k 个棋子,使用一枚棋子 一次机会
1、若棋子碎了,则t-1,k-1,递归
2、若棋子没碎,则 t-1, k不变,递归
3、循环结束返回 t
图解:
代码展示:
C++版本
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 返回最差情况下扔棋子的最小次数 * @param n int整型 楼层数 * @param k int整型 棋子数 * @return int整型 */ int calF(int k, int t) { if(t == 1 || k == 1) return t + 1; // 如果只有一次尝试机会或者棋子只有一个,则只能确定尝试机会+1数量的楼层哪一层棋子会碎 return calF(k - 1, t - 1) + calF(k, t - 1); // 非上述情况则递归(棋子-1,则机会-1)和(棋子没碎,机会-1) } int solve(int n, int k) { // write code here int t = 1; while(calF(k, t) < n + 1) t++; // 凑够n层的时候输出尝试的次数 return t; } };
复杂度分析
时间复杂度:,t就是最终的结果,其实就是尝试t的过程,一直给t赋值+1然后凑到n层为止
空间复杂度:,递归栈空间的大小
算法思想二:暴力递归(超时)
解题思路:
设计算的是n层楼时且有k个棋子,在最差的情况下需要仍的最少次数。
1、当k=0时,没有棋子,不用仍
2、当n=0时,棋子肯定不会碎,所以
3、当k=1时,只有1个棋子,只能从第1层楼开始尝试,每层都要试试:
三种特殊情况排除完,我们要看第1颗棋子仍的楼层,假设第1个棋子从第i层开始仍,那么有以下两种情况:
1、 碎了。接下来就变成了剩下i-1层楼和K-1个棋子的子问题,所以总步数为
2、没碎。没必要尝试第i层及其以下的楼层了,接下来的问题就变成了还剩下n-i层和k个棋子,所以总步数为
题目要求最坏情况,即取上述两种情况最大值再来加1(本次尝试).
因此公式为:。
复杂度分析
时间复杂度:,每次问题规模只减少1, 循环n次
空间复杂度:,递归栈深度
根据复杂度分析可知,此方法超时,不推荐使用,只做了解即可
算法思想三:二分法(一维动态数组)
解题思路:
性质:如果k充分大, 可以通过二分的方式扔棋子, 至多扔就能确定, 因此k如果大于该值, 直接返回即可
该性质可以减少大数时的运算时间。
如果令 表示i个棋子扔j次, 最多可以测多少层。那么当第i个棋子在最优的楼层扔下去时:
- 碎了。那么上面的楼层就不用测了, 下面能测的是层
- 没碎, 那么下面的楼层就不用测了, 上面能测的是层
其中第i个棋子扔掉的那一层也能被测到。
综上, 最坏情况的转移方程为:
但是可以发现的是dp[i][j]元素只和上面元素和左上角元素有关系,于是可以压缩成一维数组:
代码展示:
JAVA版本
import java.util.*; import java.lang.Math; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 返回最差情况下扔棋子的最小次数 * @param n int整型 楼层数 * @param k int整型 棋子数 * @return int整型 */ public int solve (int n, int k) { // write code here if(n<1||k<1) return 0; if(k==1) return n; int h=(int)(Math.log(n)/Math.log(2))+1; // 如果k很大, 二分的扔即可 if(k>h) return h; int[] dp=new int[k]; // 除了0,至少要扔一次,可以设为res起点 int res=1; while(true){ int p=0; // dp[1] = 1 for(int j=0;j<k;j++){ // dp[j] += dp[j-1] + 1 int temp=dp[j]; dp[j]+=p+1; p=temp; if(dp[j]>=n) return res; } // 每一轮迭代 次数增加1 res++; } } }
复杂度分析
时间复杂度:,n被二分法转化成了lgn,一个for循环为
空间复杂度:,辅助空间为一个一维数组