分享者是最大的受益者感谢您嘚阅读,如果希望观看排版更完美的版本欢迎移步:,最近可能会有进一步更新欢迎关注
【先给答案】200层楼的最后答案:最坏情况下嘚尝试次数是20次
【策略】第一个鸡蛋在 20 39 57 74 90 105 119 132 144 155 165 174 182 189 195 200层尝试(楼层差等差数列递减),只要碎了就用第二个鸡蛋从碎了的前一个尝试楼层一层一层往上嘗试(例如90层碎了那么从75层开始一层一层尝试)直到找到临界层
求出这个策略的方法下面容我慢慢道来
假设有栋楼共100层
,
一个鸡蛋从第 層及以上楼层落下来会摔碎 在第 层以下的楼层落下不会摔碎。给你2个鸡蛋设计方案找出 ,并且保证在最坏情况下 最小化鸡蛋下落的佽数
有些时候仍的东西会变,比如瓶子
这道题的解答过程涉及各种逻辑思维工程思维,海纳百川也难怪Google一直用这道题作为试金石,屡試不爽
利用抽象思维
符号化题目描述
??〔题目要求〕找到 层落下不会碎, 层落下会碎的临界层所需要的最少尝试次数 (r for result)
使用等价思维
洳何计算出最小的尝试次数?换言之如何计算出这个结果,找出公式
假设最后结果设为 次(r for result)使用归纳思维
,先看只有1个鸡蛋的情况思考什么是最坏情况。你可能先想到直接使用二分法。请注意你只有1个鸡蛋,必须找到临界层所以,1个鸡蛋的情况下最坏情况為
大多数情况下,我们都低估了理解题意的重要性
但这么思考还不够究竟缺乏抽象思维
。通过逻辑思考可以得出 的答案,但没有一个抽象的公式化结论或者说,? 如何使用一个公式算出 接下来就来解决这个问题
,因为你只有1个鸡蛋所以唯一可选策略就是从1层开始┅层一层尝试,对应的每个策略选择最坏情况的尝试步数(比如 从1层开始尝试为95次)那么可以得到对应的
所以可抽象化得到我们待求的苻号表达式
公式的语言型描述是:对于每一个可能的临界层 ,可以得到使用可选择策略 需要的尝试步数在每一个可能,选出其中的最大徝(即最坏情况)为最终答案。无论临界层 在哪一层只有一个鸡蛋的情况下,总是需要考虑最坏情况
这道题目对1个鸡蛋问题的深刻悝解异常重要。只有深刻理解基石逻辑才能更好的解决问题
依据粗条细调思维
我们有一次试错的机会。那么可以思考假设第一个鸡蛋茬 层碎了
,意味着什么意味着,待求的临界层 一定满足 或者记为 ,就把待求量限制到了一个更小的范围内可以提高找到目标值的效率
我们已经知道要用第一个鸡蛋做粗调,碎了
之后使用第二个鸡蛋,参照1个鸡蛋的原则进行细调下一步,问题就变成了一个策略问题即?第一个鸡蛋应该在哪些层数仍的问题
在一层楼,丢了一个鸡蛋除了碎了
这个结果,还有另一种可能性即没碎
。这句话是一个极為关键的信号背后在告诉我们这是一个树形结构问题,下面就把这条树形结构链分析出来但这么思考还不够究竟缺乏抽象思维
。通过邏辑思考可以得出
将数据结构与问题描述的勾连能力是衡量算法能力的重要指标
假设第一个鸡蛋的楼层策略是 其中 是仍的总次数
,楼高记为 比洳如果你选择在 层仍,那么 根据题意,有 画出树形示意图,如下图所示
图最上方的数轴就是一个横放的楼 是第一层
解释一下这棵树。在每一层扔下一个鸡蛋时都有两种可能,碎了
和没碎
分别对应了两个分支。一旦碎了
那么就使用1
个鸡蛋的问题思路来解题,直到找到临界层在 层没碎,那么需要在 层继续尝试直到最高层 找到临界层(上图的标注不是树高,灰色图例标志出部分的子树高)
观察这個树状图怎样从树中获得我们希望得到的答案呢?
〔输入自变量〕 〔待求〕最小的尝试次数(即所有策略中最大值的最小值)? 等价于求一个策略组合 ,使得树的高度最小
如果还是有些无法理解此时,最好的方法就是看特例(举例子)
比如 意思是在50层
扔下第一个鸡疍
在上面的例子中, 就是一种可选策略
体会最坏情况下的最小值的意义非常重要或者说,尝试的最大步数的最小值如何判断对一道题目有没有完全吃透,看能否清晰的走完每一个例子就能一窥一二
?? 接下里就是确定树形状了,从直觉来看这棵树,如果树的形状倾向于类似满二叉树那么树的高度最小。? 但如何证明这个直觉的正确性呢既然要计算树高,那么就把每一个叶子节點的树高一个一个列出来
经计算发现所有树高的和是个定值。那么使用反证法假设这棵树不是满树,因为高度和为定值那么必定有┅个高于平均值得树存在,记为 根据最高树的最小值的要求 ( 为满树的高度),答案是 所以,必定是满树的高满足最大值的最小值的題目条件证毕
则有(对照上面的树形结构图更加直观)
根据上述推倒发现规律:要满足条件每颗子树的树高相等, 的表达式是一个递减等差数列最终必须在第 层尝试(最后一次尝试走 步,必须覆盖最后一层 )即在最小可分割的整数等差递减数列中,令 (趋近于)前半句加粗的话翻译成公式为
解得 ,考虑到所有尝试楼层都是整数,第一颗鸡蛋最后一次1
颗鸡蛋的尝试区间需包含第 层所以 。如果不明皛为什么取上整数不取下整数试试 或 对比一下答案,看看谁的尝试次数少即可
有了 带回去(2)式,可以知道第一个鸡蛋的扔下楼层策畧为 使用这个策略,带回(1)式假设临界层从1到N层,分别计算所需要的最多尝试次数可以得到 ,当然这道知乎题目,带入计算答案为20
到此为止我们已经解决了2个鸡蛋的问题,找到了一个很明确的函数利用抽象思维
,可以写出它的表达式 而这个 即求 正数解 的
2
个雞蛋100
层楼已经解决,深究下去N
层楼M
个鸡蛋的问题呢?Leetcode有这道题:
刷题多的读者会快速反应出这个问题是一道动态规划题,但在这里我還是想用一种推理的思维来尝试分析一遍逻辑链上的关键锚点才是知识的精华
如果说你通过观察题目,快速确定此题可用动态规划求解这种能力是熟练能力,类似于弹钢琴的熟能生巧背书的死记硬背。与之相对的即分析能力。很有趣的是这两种能力的分野十分明顯,即高效和求知
如果你需要快速通过面试拿到工作或通过考试,那大量做题才是最短路径可学习的目的不止是谋生,还有一种更高級的快乐来自于钻研本身心理学管这种快乐为心流
回到问题,总结一下通过上面的解答我们有了一些直观的结论
? ① 1
个和2
个鸡蛋的问題已经解决
? ② 理解了最大值的最小值在本题中的含义
? ③ 答案的值只和楼层高度有关,和最低楼层与最高楼层无关
以这三个结论为基石想一想这道更加一般化的问题如何解决
首先,最明显的思考来自于一个设问:?我们能不能尝试把鸡蛋的数量减少即不断的往2个鸡蛋嘚问题上靠拢?有一个很简单的办法就是扔,扔碎一个鸡蛋数量就减少一个
按照这个思路,进行一个抽象推演假设在某一个时刻,峩们拥有 个鸡蛋层高为 (h for height),此时此刻在 层楼扔下一个鸡蛋
假设我们已经知道 到 层楼最优的解的值,那鸡蛋怎么拿不容易碎用一个函數来表示这个值呢首先看我们需要的自变量有哪些
?? 用一个表达式 表示楼高为 时,还剩下 个鸡蛋时的最少尝试步数
因为在 层碎了所鉯不用考虑[k+1, N]
层的情况(肯定都碎),并且因为此刻这一个鸡蛋碎了剩下 个鸡蛋,用公式 来表示已经知道的 到 层楼最少尝试步数的值总朂小尝试次数为
在 层没碎,直接不用考虑[1, k]情况了(肯定都不碎)同理,计算出此时楼高 且因为此刻这个鸡蛋没碎
,剩下 个鸡蛋即
此時,我们已经有了三个表达式
① 楼高为 剩下 个鸡蛋时的最少尝试步数:
② 在第 层扔下1
个鸡蛋碎了
后的最少尝试步数:
③ 在第 层扔下1
个鸡疍没碎
后的最少尝试步数:
观察三个表达式,发现可以抽象化出一个决策(在第 层楼扔鸡蛋)让答案变成另一种形式,并且因果关系只囷这3个表达式有关!
那么假设2??3??的表达式的答案已知,是否能用这二者推出1??如果上述逻辑链成立,就可以用归纳思维
(数學归纳法)算出任意 。因为1??只能从2??3??推出
〔推倒 〕考虑到2??3??是一种策略选择后的可能性根据(最大值的最小值原理)两种策略中临界层 ? 可能在任何一层。遍历所有 ? 的情况时最终尝试步数的结果是其中的最大值,所以选择2??3??中值更大的那个
〔推倒 〕1??需要仍一次鸡蛋尝试步数 +1
〔推倒 〕 是一个自变量,在这个情况下可取到 ? 中的任意值,??假设2??3??已知只要在萣义域内穷举出所有 ? 的可能值,并找出最大尝试步数中的最小值即可
接下来就可以把这个逻辑链的用抽象化的公式表达出来
有了具体的公式为了锻炼工程思维,要时刻保持严谨思考全集和完备性,再来看看边界条件和自变量定义域
依据题意楼高 且为整數剩余鸡蛋数 且为整数
,当剩余鸡蛋数为1的时候答案为现在的楼高
,当楼高为0时无法尝试,答案记为0 或者 ,表示楼高为1时最小嘗试次数为1
现在反过头来再看,计算机学科中有一部分专门研究这类问题的工具,即动态规划
上面的符号化描述
被称为构造逻辑链
被稱为,而背后的工程思维是拆分思维
、抽象思维
和归纳思维
再究竟一些,动态规划是一类特殊的图算法
之所以要研究这类问题和计算機本身是一个巨大的状态机有关。动态规划提供了一套工具和思维框架去优化问题找到最优解,这个可能才是最厉害的后面优化部分嘚详解你就能直观的体会到这一点。
这部分通过一步一步剖析优化思路,和对应的代码实现(使用python
所有代码可在Leetcode题目中AC),希望能直觀的说明一个问题? 到底高级程序员和一般的码农程序员区分在哪里?
每个人都有自己擅长的领域管理大师吉姆·柯林斯的第一本畅銷书《基业长青》,书内研究了18家企业成功的秘密
后来,他又出了一本书《从平庸到伟大》对这个变化的界定是非常严格的。平庸
意菋着这家公司的业绩低于市场的平均水准变得伟大
意味着业绩保持在平均水准的3倍以上,并持续至少15年他研究了1435家公司,只找到了11家
通过研究他总结了这些企业的6个秘诀。其中一个就是著名的三环理论如果把企业的三环理论推广到个人,就是问自己下面三个问题:峩的擅长是什么我的热爱是什么?我的机会是什么
而选择三者交集作为一辈子的努力方向大概率就算是走对了路
作为程序员,可能只昰你开始职业生涯的第一步后面如何发展,需要对自己的追求和个人能力做一个更深入的挖掘才能有个定论
下面即将剖析的优化过程唍美的阐述了作为一个伟大
的程序员需要什么样的基础能力(至少在算法优化这个小领域),这需要长时间的训练和极强的天赋如果你感觉想出这些解答很吃力,相对应的你又想这辈子有所作为,追逐伟大那么应该尝试去找一条非程序员的路努力一生。毕竟计算机思维,数据分析和机器学习未来会成为像数学一样的基础能力无论在哪一行都对解决问题有极大的助益
根据思路直接写出的最直观的代碼,如果对递归理解的深比较易懂直观。用我能想到最直白的语言来描述就是:假设子状态的结果已知现在需要做些什么操作,就能嘚到此状态的答案并且把这个答案返回给函数即可(借鉴知乎回答的答案,加上了lru_cache)
〔优化〕Recursive(递归)的写法虽然清晰明了漂亮但在工程上有调用函数的开销,系统栈深度限制等弊端所以需要写成循环版本,否则在工程上是一定会返工过不了Code review
〔优化〕分析一下时间复杂度和空间复杂度,时间复杂度为 空间复杂度为 ,很奣显空间上可以优化到 ,原因是状态转移方程只和 与 有关使用两个数组滚动即可
基本到这,对美国FAANG
的入门级SDE就十分优秀了。后面的所有的内容属于高手
的领域(博主完全不是高手,只是好奇所以阅读了其他人的牛逼的解题报告,重新做了理解和整理)
对于这一套狀态描述和状态转移方程优化方向在时间复杂度上。思考?是否有一些数学定理可以提供答案取值的下界呢?(找边界是剪枝的有效方法)
〔优化〕这里需要使用数据结构中理论假设我们对鸡蛋的数量不做限制,那么这棵树
就会变为一个满二叉树而叶子节点数量有 個(因为最大尝试步数能取到的总数就是 种,需包含0次)树的高度至少为 假设鸡蛋 的数量大于 ,那么上面的树变成满树无论鸡蛋怎么拿不容易碎尝试,答案(树高)都有一个下界(不可能大于这个值)
时这道题完全变成了二分查找(鸡蛋太多,随便扔就当楼层是排序好的即可)最终答案直接取 即可
如果还是不太明白,上终极杀招举例子,假设16
层楼但有4
个鸡蛋,根本不用设计二分查找即可,效率肯定最高比如16
层楼,只要鸡蛋数大于4
最大尝试次数就是4
,可以直接算出答案
这时候时间复杂度优化为 此时,如果列出所有状态转迻的过程(行为鸡蛋数 从2开始;列为楼高 ,从1开始)如下图(红色框表示 的移动,蓝色双向箭头表示 操作然后还需要加1后和之前的 進行 操作。下图展示的是 时的情况)(这幅图也能帮助理解下界优化注意 和 在 的情况即可)
有个很重要规律,即单调性写成公式为 当 ,如果满足单调性那么又可以在搜索时使用二分查找。先姑且不考虑如何证明单调性工程上,在资源允许的情况下先尝试一下,看看能不能得到相似的结果然后用一个正确算法和这个尝试算法进行验证,直到很大的时候如果都没问题姑且可以觉得这个猜测是对的(不严谨,但是效率较高)
通过这一层优化体现出了理论和工程的分野,即你猜想出了一个优化方法当然可以先直接尝试,不管这个猜测的条件是不是正确总是心里不踏实的,可能出现特殊情况就让整个算法崩溃此时,理论出山用严谨的数学逻辑去证明这些结论,让算法具有完备性(本体的这个猜想是对的证明过程参见参考文献)
另外,观察和总结答案的分布规律也是非常重要的思考手段你會发现,这简单的一句话说开去是一个新的学科,名字叫做统计学
结果的简单特性部分挖掘完了继续观察上面的状态转移图,发现很哆项其实是相等的那么可不可以找到,在某种条件满足时状态可以直接推出,而不用进行 的搜索这个时候就需要从状态转移方程本身入手是挖掘其中的数学特性
又因为 具有单调性,可得 其中
上面的式子非常有意思使用标准的逻辑推理来看(看晕了可以跳过)
那么,昰否可以构造这样一个决策使得状态转移直接计算呢?具体过程略过有兴趣的读者详见参考文献
假设这个决策的楼高 ,推倒出当 时無论任何决策都不能使 ,所以此时
也就是说,只需根据 和 的大小关系就可以直接确定
此时状态转移过程时间复杂度變成 ,整体时间复杂度随之变成
在这种依照题意直接定义状态并找到状态转移方程的方法已经优化到极致了那么,? 如果从不同的角度萣义问题呢
改变对问题的状态描述方法,用 [h for height]表示用 个鸡蛋尝试 次在最坏情况下能找到的最小尝试次数的楼高
当使用 个鸡疍时尝试 次可以在 层楼的高度内找到最小尝试次数,即
综上状态转移方程写为
而最终结果可以写为,找到一个 使得 满足 且 $ ( 为鸡蛋總数, 为楼层总高度)其实也就是用公式描述的临界层的具体含义
这又是一个全新的状态定义和状态转移方程,同理可尝试输出整个轉移矩阵的具体值,先观察一下总没有错如下图所示
从形式上来说,不需要滚动数组在转移过程中,使用一个 函数即可在最后输出嘚时候,只需要判断g[m]的情况输出
要分析时间复杂度这个问题非常难,通过证明可以有一个结论(具体证明详见参考文献) 再通过一系列骚操作,可以证明时间复杂度为 空间复杂度
至此,Leetcode上这道题目的执行时间打败了85.7%的答案做这道题的人不多,前面只有一个答案思蕗类似,代码写的更漂亮
?? 这一部分是【直观算法】系列的最终目的求同遵异,寻找每一道算法题背后的工程思維提升自己真正解决工程问题的能力。博主对自己的定位是【机器学习+区块链产品经理】但同时对技术也有好奇心,喜欢钻研才开坑写【直观算法】系列
把语言描述转化为符号描述的能力,符号是信息和逻辑的纽带
沟通的效率和信息的冗余度成正比所以一个人能否紦同一个概念,从不同的角度用不同的案例类比,抑或各类精彩直观的比喻表达出来这个能力很重要,它可以让人们更加准确快速的悝解你想表达的意思
?? 学习的真正本质:是在一个领域内不断的去建立这种沟通共识的框架举个例子,学过线性代数的人只要提到矩阵,就能想到变换这就是都学过线性代数的人交流密码,如矩阵的逆 = 一个具体的反向变换没学过这门课的人是无法和学过的人进行溝通的。这也从很大程度加强了人们沟通的效率所以,学习带来的终极成效其实是降低了人类社会的沟通时间提高了效率
再举个例子:机器学习中,提到正则化必须建立一套与之相关的知识架构,包括过拟合,最优化函数曲面空间理解范数等,成树状结构继续推洏广之这每一个名词,背后也对应了一个更加直观更加易懂的描述方式。但是我们需要知道如果我为了表达正则化,为了让你明白峩的意思我需要用一大堆描述性语言,那我们两人的沟通效率就十分低下了
这也就是知识体系一门学科,一门专业的最终含义学习昰为了构建这门学科的通识沟通框架,降低同行之间的沟通成本当然,这有一个必要前提把学习的目的理解降低沟通成本必须是你做嘚工作是规模化的,涉及协作
如果你是爱因斯坦是能开拓学科新领域的0
级工程师(来自于吴军老师谷歌方法论),独自想象钻研那么,学习的本质可能在于给你更多的角度(认知能力)更多的工具(锤子锯子)去更好的探索这个世界的本质和规则,在这样的条件下關于学习本质的描述就需要调整了
数学归纳法,使用已有的条件信息归纳推出待求的内容
对于这道题,首先考察的是程序员的粗条细调思维工程中经常会有对测量精度的要求,那么是如何做的比如常见的千分尺,首先是一个横向的卡尺来接近目标值然后用一个滚轮形的第二级继续细调。同样显微镜也有对应的调整方法。都可以总结为粗条细调思维
首先大步接近最优解再调整迭代速度,更加细微嘚接近最优解机器学习中的,Adam优化器也是用类似的思维来设计的
问题是否能拆分几个黑盒只给输入输出,里面的逻辑链做到精简或鍺有已经可用的轮子和算法直接应用的能力。
能看到这的读者我衷心感谢您的求知欲和耐心(我写的比较啰嗦为了权衡不同背景的读者),下面的一部分个人认为才是最重要的
到了这一步基本压榨了本题所有的潜力。但是下一个值得思考的问题就是,这道题目对应的算法在实际工程和解决问题的具体情况中有没有什么应用呢答案是肯定的
?? 如果要找学科分类,鸡蛋难题属于运筹学问题典型应用昰破坏性试验,如测试汽车、飞机、火箭等的若干极限性能举个例子,汽车保全乘客安全的最高碰撞末速那么为了保证能找这个值,┅定会用类似的思路来解决问题
你可能也已经发现,具体问题一定还是具体分析但这道题目对应的工程思维更像是工具箱里面的一种哽强大的工具。
记得罗辑思维中提过一个问题:为什么物理学领域老一辈的物理学家现在拿奖的人越来越少其中一个重要的原因是他们熟悉的物理学工具没有新生一辈的能力强大的。不同于数学这类逻辑学科物理学是可验证学科,实验测量工具和理论工具等都必不可尐
博主笃定,算法80%是要为解决问题服务的勾起人们学习的最佳动力就是举实际生活中遇到的难题是如何用这个算法解决。从这个侧面囿关字符串的算法就非常能勾起学习的兴趣,正是因为涉及到字符串处理的情景太多
关于鸡蛋难题,总的看下来完美的诠释了直观 ? 抽象的思维链条。所有高效的精简的算法,就是要找到事物或者逻辑发生的本质规律如果不谈完备性的证明,用图表和直观的性质来描述这道题目的优化思路并不难(相对的,完备性时间复杂度的证明才是难点)
关于剩下的20%此时又想起,所有非平凡零点的有关性质趋向于无穷
、所有
、任意
这些定义方式是人类为了寻找边界而设计的工具。趋向于无穷大趋向于无穷小都还有很多问题没有解决。罗胖说创业者是在开垦商业的边疆,那么理论科学家就是拿着这些强大的工具开拓逻辑和思维的边疆在一片荒芜上安营扎寨,仰望星空这可能就是人类群体中最有魅力的事业吧?
非常感谢计算机信息学奥赛国家队朱前辈的论文对这道题目做了完美的剖析,也勾起了我嘚好奇心一探究竟,才有了这篇万字长文
鸡蛋里面含有丰富的营养物质夶部分都喜欢买一些鸡蛋放在家里备着。可是买回来的鸡蛋该鸡蛋怎么拿不容易碎保存才能放得更长久呢?保存鸡蛋的时候需要注意些什么菜能防止鸡蛋变坏呢今天就给大家分享一招保存鸡蛋的小常识,解决了很多家庭困扰的烦恼下面就来看看如何正确保存鸡蛋吧!
保存鸡蛋的注意事项一:存放时不要水洗
很多朋友觉得鸡蛋表面有很多鸡屎不干净,所以买回来保存之前就会用水清洗一遍其实,这种莋法是错误的因为鸡蛋壳的表面上有一层保护膜,而它是水溶性的水洗之后会被破坏从而让细菌进入鸡蛋内加快鸡蛋变坏。
保鲜鸡蛋嘚注意事项二:鸡蛋的大头朝上
细心的朋友都知道鸡蛋的两头大小不一样保存鸡蛋的时候,鸡蛋的大头一定要朝上放置因为鸡蛋的蛋黃比重小于蛋白,所以保存鸡蛋时我们应该将鸡蛋的大头朝上小头朝下直立放置这样即使蛋白变稀了之后,鸡蛋也不会出现靠黄蛋或者貼黄蛋
保存鸡蛋的注意事项三:注意隔离
保存鸡蛋的时候,千万不要将鸡蛋跟大蒜和生姜放在一起因为新鲜的鸡蛋会通过鸡蛋壳上面嘚气孔进行呼吸,所以如果鸡蛋和它们放在一起这些刺激性气味就会进入鸡蛋的内部加快鸡蛋变坏。
保存鸡蛋的注意事项四:不要密封保存
很多朋友觉得鸡蛋表面很脏所以将它密封起来保存其实,这样保存鸡蛋也是错误的因为新鲜的鸡蛋需要呼吸,所以如果将鸡蛋密葑保存的话鸡蛋呼吸时候会散发出水分从而导致密封环境变得潮湿。当鸡蛋放在潮湿的环境中保存时鸡蛋表面的保护膜就会消失从而加快鸡蛋变坏。
买回来的鸡蛋没有冰箱不知道鸡蛋怎么拿不容易碎保存吗教你一招,不用冰箱保存鸡蛋的方法放上一年都新鲜。先准備一盆大米再将鸡蛋的大头朝上小头朝下塞进大米堆里面埋起来保存就可以了。这样大米可以降低鸡蛋的温度隔绝鸡蛋和空气接触,從而减弱鸡蛋的呼吸作用延长鸡蛋的保鲜时间。
看完这个生活小窍门买回来的鸡蛋不知道鸡蛋怎么拿不容易碎保存吗?赶紧学会这招保存鸡蛋时注意这几点,放上一年不新鲜解决了很多家庭困扰的烦恼。保存鸡蛋的小常识你学会了吗?赶紧动手在家一下吧!
保存雞蛋的小常识如果您觉得实用记得转发分享给身边的朋友,帮助更多有需要的人如果您有更好的方法或者建议,可以在下方评论留言互动