美文网首页
【LintCode】254. 丢鸡蛋

【LintCode】254. 丢鸡蛋

作者: Kean_Qi | 来源:发表于2020-05-11 22:18 被阅读0次

楼有 n 层高,鸡蛋若从 k 层或以上扔,就会碎。从 k 层以下扔,就不会碎。
现在给两个鸡蛋,用最少的扔的次数找到 k。返回最坏情况下次数。

【要求】找到x层落下不会碎, x+1层落下会碎的临界层所需要的最少尝试次数 r(r for result)

【假设】

  • 只有1鸡蛋测试,需要从1层开始一层一层实验,最坏次数为k
  • 如果有两个鸡蛋,第一个鸡蛋用来试探, 只要它从 k 层楼扔下去没碎, 则目标就在[k+1, n]之间了.但一旦运气不好碎了, 对于已知的区间, 我们只能用剩下一个鸡蛋从小到大一层层试,因为我们要保证策略必须成功, 不能冒险了.
    "最坏情况下代价最小"这句话十分重要, 它反映了题目的重要数学结构:
    我们可以把任何一种策略都看成一个决策树,每一次扔鸡蛋都会有两个子节点, 对应碎与不碎的情况下下一步应该扔的楼层.
    那么, 策略的一次执行, 是树中的一条从根往下走的路,当且仅当这条路上出现过形如 k 没碎 与 k+1 碎了的一对节点时, 路停止, 当前节点不再扩展.
    那么要找的是这么一棵树, 使得所有路里最长者尽量短, 也即, 要找一个最矮的决策树.
    再看一个节点处, 选择楼层时会发生什么.
    容易看出, 选择的楼层如果变高, 那么"碎子树"高度不减, "不碎子树"高度不增.
    同样的, 选择的楼层变矮的话, "碎子树"高度不增, "不碎子树"高度不减.
    这时候答案很明显了: 为了使两子树中高度最大者尽量小, 我们的选择应当使两子树高度尽量接近.
    最终希望的结果是, 整个二叉树尽量像一个满二叉树.
  • 假设第一次在根节点上, 我们选择扔k层, 其"碎子树"的高度显然是k - 1.
    为了考虑不碎子树的高度, 设不碎后第二次扔m层(显然m > k ),
    则这个新节点的碎子树高度为 m - k - 1, 不碎子树高度仍然未知,
    但按照满二叉树的目标, 我们认为它与碎子树相同或少1就好.
    那么在根节点上的不碎子树的高度就是m -k-1 + 1, 令它与碎子树高度相同, 于是:
    m - k - 1 + 1 = k - 1 => m = k + k - 1
    也即, 如果第一次扔在k层, 第二次应该高k-1 层, 这可以有直观一点的理解:每扔一次, 就要更保守一些, 所以让区间长度少1. [1, k) -> [k + 1, 2k - 1).用类似刚才的分析, 可以继续得到, 下一次应该增高k - 2, 再下一次应该增高k - 3.

如果大楼100层, 考虑:
k + (k-1) + (k-2)+...+3+2+1 = (k+1)*k/2 =100 =>k ~= 14
所以第一次扔14层, 最坏需要14次(策略不唯一, 树的叶子可以交换位置).
以上是数学做法...当然还有代码做法....
设f(n, m)为n层楼, m个蛋所需次数, 那么它成了一道DP题..

f(0,m) = 0,(m>=1)
f(h,1) = n,(h>=1)
f(h,m) = (1->k->n)min{max{f(k-1,m-1), f(h-k, m)}} + 1
即:


f(h,m) = (1->k->n)min{max{f(k-1,m-1), f(h-k, m)}} + 1.png
public class Solution {
    /**
     *
     * @param n 楼层
     * @return  最坏情况最少的次数
     */
    public int dropEggs(int n){
         long k = 0;
        for (int i = 1; ; ++i) {
            k += (long)i;
            if (k >= (long)n)
                return i;
        }
    }

另外一种暴力方法:

public int dropEggs(int n) {
        long x = n;
        double x1 = (Math.sqrt(x * 8 + 1) - 1) / 2;
        return (int)Math.ceil(x1);
    }

相关文章

  • 【LintCode】254. 丢鸡蛋

    楼有 n 层高,鸡蛋若从 k 层或以上扔,就会碎。从 k 层以下扔,就不会碎。现在给两个鸡蛋,用最少的扔的次数找到...

  • [leetcode/lintcode 题解] 快手面试题:丢鸡蛋

    【题目描述】 有一个n层的建筑。如果一个鸡蛋从第k层及以上落下,它会碎掉。如果从低于这一层的任意层落下,都不会碎。...

  • 2018-5-31 星期四

    早餐:小米粥 鸡蛋 午餐:餐盘 --- 韭菜鸡蛋、土豆丝、茄子 (吃了一丢丢,太难吃....) 下午:一根香蕉 ...

  • 【宅家减肥】酱油蒸鸡蛋

    宅家减脂 减肥期间一天吃几个鸡蛋? 【酱油鸡蛋】 食材准备:鸡蛋6个; 调料:海鲜酱油一勺、一丢丢盐巴、一小把葱花...

  • 9.6 - medium - 121:160

    练手题: 254. Factor Combinations *261. Graph Valid Tree264. ...

  • 程序员常用的刷题网站

    1、Lintcode Lintcode.com——LintCode网站是国内较大的在线编程&测评网站。此网站提供各...

  • Singleton

    lintcode: http://lintcode.com/en/problem/singleton/ Java ...

  • 西红柿鸡蛋盖浇面

    前几天,在楼下的餐馆里给孩子打包了份西红柿鸡蛋面,16元,只有一丢丢西红柿汁,鸡蛋炒的稀碎,看着都没食欲。 怪不得...

  • 二叉树非递归遍历——已通过LintCode

    先序遍历 LintCode题目链接 中序遍历 LintCode题目链接 后序遍历 LintCode题目链接由于在L...

  • Algorithms ladder I

    24 Dec Mission: lintcode 13 strStr lintcode 17 Subsets li...

网友评论

      本文标题:【LintCode】254. 丢鸡蛋

      本文链接:https://www.haomeiwen.com/subject/iaqpnhtx.html