美团2020算法工程师问答题--黑客入侵定位

8 篇文章 0 订阅
2 篇文章 0 订阅

题目描述:

【黑客入侵点定位】集团内部有一核心机密项目,共由150个代码模块按顺序串行执行组成(示例:模块1->模块2->…模块N…->模块149->模块150)。偶然一天,某一个模块突然被黑客入侵(当前模块也称入侵点)。因为内部已经有预防措施,现存两款从不同角度设计的反入侵检测程序,但同时也有一定检测限制:
1.输入:顺序代码段,必须以模块1开始(比如:模块1->模块2->…模块39)
2:输出:True-输入包含入侵点,False-输入不包含入侵点
3.每款检测程序可以运行多次:可多次返回False,但仅能返回一次True(由于入侵的对抗性存在,一旦输出True即报废,后续检测功能失效)
4.同一时刻只能有一款检测程序运行,每检测一次耗时10分钟
现在希望仅利用现有的两款反入侵检测程序,在最短的时间内确保可以快速定位入侵点。具体需要如何设计检测流程,时间是多久。

题目分析:

这道题和谷歌经典面试题高楼扔鸡蛋问题很类似,题目描述如下:
两个软硬程度一样但未知的鸡蛋,它们有可能都在一楼就摔碎,也可能从一百层楼摔下来没事。有座100层的建筑,要你用这两个鸡蛋通过最少的次数确定哪一层是鸡蛋可以安全落下的最高位置。可以摔碎两个鸡蛋

思路分析:分析这个问题,最简单的思路便是一楼一楼的试,这样的话最坏的情况需要试100次,当我们手里只有一个鸡蛋时,该方法确实是最稳定的方法,但是我们手里有两颗鸡蛋,因此可以尝试进阶解法。

进阶解法:很明显,当手里有两个鸡蛋时,可以考虑二分法,第一个鸡蛋用来探路,第二个鸡蛋用来具体确定楼层。例如,第一个鸡蛋从50楼扔下去,如果没碎,则第一个鸡蛋继续使用,从第75楼扔下去,如此递推,而如果从50楼扔下去碎了,则第2歌鸡蛋,需要从第1楼到第49楼一层一层确定,最坏的情况时在第49楼刚好扔下去碎了,此时一共扔的次数为50次,比从一楼一楼往下扔需要的次数还要多。

上面的分析都是从鸡蛋的角度出发,但是换一个思路,从楼层的角度出发,就会发现这是一个很明显的动态规划的问题。

动态规划的解法:假设有n个楼层,第一个鸡蛋冲第i层扔下,那么如果碎了,则第二个鸡蛋最糟糕的情况下需要尝试i-1次,总的便是1+(i-1)次,如果没碎,两个鸡蛋都在,则需要尝试的次数为1+从n-i层楼用两个鸡蛋确定临界楼层的问题,也就是说假设用两个鸡蛋确定100楼的临界层数需要尝试的次数为f(100),则从n-i层楼用两个鸡蛋确定临界楼层需要尝试的次数为f(n-i),即鸡蛋从第i楼扔下没碎的情况下,最多需要尝试的次数为1+f(n-i),那么从第i楼仍鸡蛋最糟糕的尝试次数为1+max(i-1, f(n-i)),而f(100),就是对i从1到100时1+max(i-1, f(100-i))最小的那一个。

  • 迭代公式:f(n) = min(1+max(i-1, f(n-i))),其中max是针对i-1,f(n-i)而言,min是针对i从1到100而言。
  • 初始状态,假设有0个楼层,很明显f(0)=0,假设有1个楼层,则鸡蛋从1楼扔下,不管碎没碎都可以确定临界层,因此f(1)=1
  • python实现代码:
import sys

def minLayer(n):
    if n<=0:
        return 0
    if n == 1:
        return 1
    min_layer = n
    for i in range(1, n+1):
        layer = 1 + max(i-1, minLayer(n-i))
        if layer < min_layer:
            min_layer = layer
    return min_layer

if __name__=='__main__':
    n = int(sys.stdin.readline().strip())
    min_layer = minLayer(n)
    print(min_layer)
  • 扩展到有m个鸡蛋的解法:当从i层扔下时,如果没碎,则最糟糕的次数为f(n-i, m) + 1,如果碎了,则最糟糕的次数为f(i-1, m-1) + 1,也就是说从i层扔下,最最糟糕的次数为max(f(n-i, m), f(i-1, m-1)) + 1,其对应的实现代码为:
import sys

def minLayer(n, m=2):
    if n<=0:
        return 0
    if m == 1:
        return n

    min_layer = min([max([minLayer(i-1, m-1), minLayer(n-i, m)]) for i in range(1, n+1)]) + 1
    return min_layer

if __name__=='__main__':
    n = int(sys.stdin.readline().strip())
    min_layer = minLayer(n)
    print(min_layer)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值