丢鸡蛋问题的拉格朗日插值多项式解法

假如有K个鸡蛋,一栋N层的楼,为了测试鸡蛋最高在哪一层扔下刚好不碎,并且扔鸡蛋的次数最少。假设鸡蛋碎了就不能用了,没碎的话可以继续使用。
这也是google曾经的面试题,解决方法有很多,
1、枚举法(最保守的扔法,最多碎一个鸡蛋)
只能从第一层逐层往上扔, 但是这样最坏的情况需要扔N次才能知道答案。方法优点是碎的鸡蛋少,缺点是测试的次数多。
2、二分法(高效的扔法,比较耗鸡蛋)
先从楼层中间开始扔,如果碎了就往更低的楼层扔,没碎就往更高的楼层扔。方法优点是测试次数少,缺点是二分后扔鸡蛋的楼层相比枚举法,鸡蛋碎的风险更高,所以在鸡蛋足够多的情况下这样的扔法可以很快的找到答案。
3、全局平衡公式算法(个人理解的)
从开始往结局做一次全局平衡,使得开始到结局的每一次结果对于最终的答案影响都尽量是一样的,感觉和动态规范方向相反,特殊情况下和动态规划效果是一样的。
4、动态规划
百科中说到动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
上面都是复制粘贴的,下面是正文,用纯数学的方式求解。
f ( k , n ) f(k,n) f(k,n)表示用 k k k个鸡蛋,丢 n n n次,最多能测试出多少层。容易看出,
f ( 1 , n ) = n f(1,n)=n f(1,n)=n
如果有两个鸡蛋,假设第一个鸡蛋在第 m m m层楼丢下,有两种结果,

  • 鸡蛋碎了,那么剩下一个鸡蛋,还需要测试的次数 n 1 n_1 n1满足 f ( 1 , n 1 ) = m − 1 f(1,n_1)=m-1 f(1,n1)=m1
  • 鸡蛋没碎,剩下两个鸡蛋,还需要测试的次数 n 2 n_2 n2满足 f ( 2 , n 2 ) = h − m f(2,n_2 )=h-m f(2,n2)=hm h h h代表最多能测试的楼层高度。为了在固定最坏情况测试次数,必有 n 1 = n 2 = n − 1 n_1=n_2=n-1 n1=n2=n1,因此,
    h = f ( 2 , n ) = f ( 1 , n − 1 ) + f ( 2 , n − 1 ) + 1 h=f(2,n)=f(1,n-1)+f(2,n-1)+1 h=f(2,n)=f(1,n1)+f(2,n1)+1
    同理,
    f ( k , n ) = f ( k − 1 , n − 1 ) + f ( k , n − 1 ) + 1 f(k,n)=f(k-1,n-1)+f(k,n-1)+1 f(k,n)=f(k1,n1)+f(k,n1)+1
    由于 f ( k , n − 1 ) = f ( k − 1 , n − 2 ) + f ( k , n − 2 ) + 1 f(k,n-1)=f(k-1,n-2)+f(k,n-2)+1 f(k,n1)=f(k1,n2)+f(k,n2)+1,将上式展开,得到,
    f ( k , n ) = 1 + ∑ i = 1 n − 1 f ( k − 1 , i ) f(k,n)=1+\sum_{i=1}^{n-1}{f(k-1,i)} f(k,n)=1+i=1n1f(k1,i)
    边界条件为
    { f ( 1 , n ) = n f ( k , 1 ) = 1 \left\{\begin{matrix} f(1,n)=n\\ f(k,1)=1 \end{matrix}\right. {f(1,n)=nf(k,1)=1
    可以得到
    f ( 2 , n ) = n + ∑ i = 1 n − 1 f ( 1 , i ) = n ( n + 1 ) 2 f\left(2,n\right)=n+\sum_{i=1}^{n-1}f\left(1,i\right)=\frac{n\left(n+1\right)}{2} f(2,n)=n+i=1n1f(1,i)=2n(n+1)
    f ( k , n ) = n + ∑ i = 1 n − 1 f ( k − 1 , i ) f\left(k,n\right)=n+\sum_{i=1}^{n-1}f\left(k-1,i\right) f(k,n)=n+i=1n1f(k1,i)
    容易证明, f ( k , n ) f(k,n) f(k,n)是关于 n n n k k k次多项式,设
    f ( k , n ) = c 0 + c 1 n + c 2 n 2 + … + c k n k f\left(k,n\right)=c_0+c_1n+c_2n^2+\ldots+c_kn^k f(k,n)=c0+c1n+c2n2++cknk
    由于 k k k次多项式可以由 k k k个采样点确定,为了方便计算,可设 f ( k , 0 ) = 0 f\left(k,0\right)=0 f(k,0)=0,从而 c 0 = 0 c_0=0 c0=0 f ( k , n ) f(k,n) f(k,n)可由剩下的 k k k个点确定。根据递推式,
    f ( 1 , 1 ) = 1 f(1,1)=1\\ f(1,1)=1
    { f ( 2 , 1 ) = 1 f ( 2 , 2 ) = f ( 1 , 1 ) + f ( 2 , 1 ) + 1 = 3 \left\{ \begin{matrix} f(2,1)=1 \\ f(2,2)=f(1,1)+f(2,1)+1=3 \end{matrix} \right. {f(2,1)=1f(2,2)=f(1,1)+f(2,1)+1=3
    { f ( 3 , 1 ) = 1 f ( 3 , 2 ) = f ( 2 , 1 ) + f ( 3 , 1 ) + 1 = 3 f ( 3 , 3 ) = f ( 2 , 2 ) + f ( 3 , 2 ) + 1 = 7 \left\{ \begin{matrix} f(3,1)=1\\ f(3,2)=f(2,1)+f(3,1)+1=3\\ f(3,3)=f(2,2)+f(3,2)+1=7 \end{matrix} \right. f(3,1)=1f(3,2)=f(2,1)+f(3,1)+1=3f(3,3)=f(2,2)+f(3,2)+1=7
    更一般的,对于 1 ≤ n ≤ k 1\le n\le k 1nk,有
    f ( k , n ) = 2 n − 1 f\left(k,n\right)=2^n-1 f(k,n)=2n1
    已知 k + 1 k+1 k+1个点,求 k k k次多项式,将定义域扩展到实数域,利用拉格朗日插值多项式,令
    l j ( x ) = ∏ i = 0 , i ≠ j k ( x − i ) ∏ i = 0 , i ≠ j k ( j − i ) l_j\left(x\right)=\frac{\prod_{i=0,i\neq j}^{k}{(x-i)}}{\prod_{i=0,i\neq j}^{k}{(j-i)}} lj(x)=i=0,i=jk(ji)i=0,i=jk(xi)

    f ( k , n ) = ∑ j = 0 k ( 2 j − 1 ) l j ( x ) f\left(k,n\right)=\sum_{j=0}^{k}{(2^j-1)l_j(x)} f(k,n)=j=0k(2j1)lj(x)
    对于给定的 k k k n n n,若 n ≤ k n\le k nk,则 f ( k , n ) = 2 n − 1 f\left(k,n\right)=2^n-1 f(k,n)=2n1,若 n > k n>k n>k,则 l j ( n ) l_j(n) lj(n)的分子部分仅有一项缺失,分母转化为两个阶乘因子,
    l j ( n ) = ∏ i = 0 k ( n − i ) ( n − j )   ( − 1 ) i − 1 ( i − 1 ) ! ( k − i ) ! l_j\left(n\right)=\frac{\prod_{i=0}^{k}\left(n-i\right)}{\left(n-j\right)\ \left(-1\right)^{i-1}\left(i-1\right)!\left(k-i\right)!} lj(n)=(nj) (1)i1(i1)!(ki)!i=0k(ni)
    对于不同的下标 j j j,分子相同,分母通过增量计算,可以在 O ( k ) O(k) O(k)时间内计算完成。
    现在处理最后一步,原题是给定 k k k个鸡蛋和 h h h层楼,而上面计算的是丢 n n n次最多能测试多少层楼,因此要求的是满足 f ( k , n ) ≥ h f(k,n)\ge h f(k,n)h的最小的 n n n。若 h < 2 k h<2^k h<2k,则 n = ⌈ log ⁡ 2 ( h + 1 ) ⌉ n=\left\lceil\log_2{(h+1)}\right\rceil n=log2(h+1),否则,由于 f ( k , n ) f(k,n) f(k,n) [ n , + ∞ ) [n,+\infty) [n,+)是递增的,可使用牛顿迭代法快速得到 x h x_h xh,满足,
    f ( k , x h ) = h f\left(k,x_h\right)=h f(k,xh)=h
    从而求得 n ∗ = ⌈ x h ⌉ n^\ast=\left\lceil x_h\right\rceil n=xh
  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值