zoukankan      html  css  js  c++  java
  • 一道有趣的Twitter技术面试题

    来自:http://blog.jobbole.com/50705/

     

    看下面这个图片”

    “在这个图片里我们有不同高度的墙。这个图片由一个整数数组所代表,数组中每个数是墙的高度。上边的图可以表示为数组[2,5,1,2,3,4,7,7,6]”

    “假如开始下雨了,那么墙之间的水坑能够装多少水呢?”

    “以1×1的方块为单位计算容积。所以,在上边的图中下标为1以左的都会漏掉。下标7以右的也会漏掉。剩下的只有在1和6之间的一坑水,容积是10”

     

    ---------------------------------------------------------------

    我大概用了30分钟想到了解法,但是翻译成可执行代码用了大半天.

    原因一是我的思维过程其实包含了大量的默认判断,对于人脑很自然,但是对于机器就得一一明确指出.

    二是我一开始设计了个复杂的数据结构,导致测试过程中的索引让我头脑混乱.后来肉眼观察代码的字符规律,发现完全可以用一个简单的数组代替...肉眼发起的优化啊= =..

    为什么会犯这种错误,因为一开始我有种多多益善的倾向,把衍生数据和原始数据都放到一个元组里面吧,万一哪个地方所有数据都需要呢?

    下面是我的解法.思路是先将这些墙按其高度从高到低排列形成一个新表arr2,arr2的数据本身不是高度,而是这个高度在arr中的索引.然后再遍历arr2,检查两墙之间能累积多少水.

    代码:

    arr=[2, 5, 1, 2, 3, 4, 7, 7, 6]
    
    def waterWall(arr):
        #print arr
        #print arr2
        #[2, 5, 1, 2, 3, 4, 7, 7, 6]
        #[7, 6, 8, 1, 5, 4, 3, 0, 2]
        
        def calWater(big,sml):
            #根据传入的2个墙的索引值计算它们之间的水容量
            #水容量是由较矮的墙决定的
            shorter=min(arr[sml],arr[big])
            return sum((shorter-mid for mid in arr[sml+1:big]))
        #按墙高倒序排列的索引值数组,最左边的成员表示最高的墙的索引值,以此类推
        arr2=map(lambda x:x[1],
                 sorted(((k,i) for i,k in enumerate(arr)),
                        reverse=1))
        #已检查的区域,用于控制计算以及退出循环
        ckdRange=[]
        #总水量
        waterVol=0
    
        end=len(arr2)-1
    
        #首次循环是计算2个成员,以便初始化区域
        #之后的循环将成员sml和ckdRange的上下界比较
        for i in range(end):
            big,sml=arr2[i],arr2[i+1]
            #如果是首次循环,那么初始化ckdRange和水量
            if not ckdRange:
                #墙更高不一定索引更大,保证sml指代较小数,简化判断
                if sml>big:
                    sml,big=big,sml
                #传入两墙的索引,开始累积水量
                waterVol+=calWater(big,sml)
                #初始化已检查的区域
                ckdRange.extend([sml,big])
            elif sml>ckdRange[1]:
                waterVol+=calWater(sml,ckdRange[1])
                ckdRange[1]=sml
            elif sml<ckdRange[0]:
                waterVol+=calWater(ckdRange[0],sml)
                ckdRange[0]=sml
            #如果区域已经覆盖全部成员,那么退出循环
            #最极端的情况是arr首尾成员是最高墙时,只需迭代一次就退出
    
            #print 'range checked:',ckdRange,'water:',waterVol
            if ckdRange==[0,end]:
                break
        #返回最终水量
        return waterVol
    
    print waterWall(arr)
  • 相关阅读:
    无法添加sql server ER图
    我和COC
    WordPress怎样设置菜单栏旋转小图标
    VS Code怎样设置成中文
    初探 Git Submodules
    使用 rsync-deploy-action 同步 Hexo 博客到个人服务器
    Latex基本语法简记
    SQLAlchemy建立数据库模型之间的关系
    Flask的请求钩子与上下文简览
    如何将本地项目推送到Github
  • 原文地址:https://www.cnblogs.com/xiangnan/p/3402467.html
Copyright © 2011-2022 走看看