lintcode 丢鸡蛋
描述
楼有n层高,鸡蛋若从k层或以上扔,就会碎。从k层以下扔,就不会碎。
现在给两个鸡蛋,用最少的扔的次数找到k。返回最坏情况下次数。
样例
对于n=10, 一种找k的初级方法是从1、2…k层不断找。但最坏情况下要扔10次。
注意有两个鸡蛋可以使用,所以可以从4、7、9层扔。这样最坏就只需要4次(例如k=6时)。
给出 n = 10, 返回 4.
给出 n = 100, 返回14.
思路
先从最简单的方式丢起,一层一层扔,这样最坏的情况下需要的一定是n次,因为有两个鸡蛋,我们可以利用这一点将n层楼分段。
比如,对于12层楼高,可以从第四层开始扔,如果第四层碎了,只剩下一个鸡蛋,只能从1楼开始扔,这样就最多需要3+1 = 4次,如果第四层没有碎,就利用第一个鸡蛋继续分层,下面分层就有说法了,如果是从第8层开始扔,那么最坏是需要5次(k = 7),这样分不是我们想要的,因为如果没有碎,继续往上丢,下一次就是12层,当k=11时,需要6次才能得到这个k。
设楼高是n,第一种方式是等间隔扔,间隔是m(方便起见,假设m是n的一个因数),那么得到的试验次数就是n/m+m-1次,即最后一个间隔的倒数第二个,利用不等式,最小是2n-1。第二种方式是每次间隔少1,设初始间隔为i(为了方便,同样满足i+i-1+i-2+…+1 = n),可以算出i = (-1 +1+8n) / 2,可以判断出 i是比2n-1还要小的,那么就通过计算得出了等间隔得出的结果在最坏情况下并不是最少的。
这样的话,第一次选择的间隔实际上就已经决定了最大的试验次数,也就是返回值。
下面问题来了,每次选择的间隔比上一次少,少几呢?刚才的计算方法是少1,如果是少2的情况,最差的情况就是第一个间隔的倒数第二个,最差情况下不会比少1好,所以不用再考虑间隔差更大的情况了。
综上所述,只需要决定初始间隔大小,就决定了返回的最少的最差试验次数。即i+i-1+i-2+i-3…+2+1>=n的最小i.
代码
class Solution {
public:
/*
* @param n: An integer
* @return: The sum of a and b
*/
int dropEggs(int n) {
// write your code here
double res = 0;
for(;;res++) {
double sum = (1 + res) * res / 2;
if (sum >= n)
return res;
}
}
};