小米笔试:“杨辉三角”&“排排坐吃果果”|掘金技术征文

或许每个武大的学生,都会对小米有不同的情怀吧。
毕竟雷军做为武大杰出校友已经名满天下,创业经历也足够励志传奇,对学校的情怀也是特别吸粉的一点。
今年4月回武大颁发“雷军奖学金”以后,微博那句“愿你走出半生,归来还是少年”简直戳中无数少女心,想进小米的情愫早已在心底根种。
javascript


因此9月18号小米的笔试我也是尤为用心了,晚上六点半早早坐在电脑前等着,也许我与学长的距离经过这俩小时就大幅缩进了呢。
这里跟你们分享其中两个完整的前端编程题:“杨辉三角”和“排排坐吃果果”(哈哈,这是我给取的名,原谅写程序的小女生就这点乐子了,先卖个关子,到下面跟你们解释)。

题一描述:前端

一个整数三角形,三角形的每一行都比上面一行多出一个数字(第1行有1个数字,第2行有2个数字,以此类推);每一个数字,都等于它上方(若是有的话)与左上方两个数字之和,以下图所示:
java


如今给出一个数,请算出它最开始出如今第几行?
输入:一个正长整形数,保证为长整形的正数。
输出:这个数最开始出现的行数。

拿到题第一感受很亲切,感谢小学数学老师天天放学后额外留给个人奥数题,谁也没想到会在十几年后再次碰见“杨辉三角”。过后在网上一搜,发现巨多用编程语言打印出来的“杨辉直角”,C、C++、C#、JAVA……看来你们都是如此的富于乐趣啊算法

回归正题,一开始想拿着数字去反推,这果断是个错误。
还好思路立刻刹车转弯,把这个直角三角形写出来打印出来啊,
每打印一行我就判断一次,判断这一行里有没有给的这个数。编程

window.onload=function(){
    function countNum(x){       
        if(x==1){return 1}      //函数输入1直接返回1
        var arr=[[1],[1,1]]        //定义数组初始值
        for(var i=2;i<x+1;i++){ //从第三行开始建立数据
                arr[i]=[]            
                arr[i].push(1)        //每一行第一个默认为0 
                for(var j=1;j<i;j++){    //从每一行第二列开始遍历
                    arr[i].push(arr[i-1][j-1]+arr[i-1][j])
                    //每一个数字,都等于它上方(若是有的话)与左上方两个数字之和
                }
                arr[i].push(1)        //每一行最后一个也是1
                if(arr[i].indexOf(x)>0){    //完成一行遍历后,查看这一行中有没有须要的数
                    console.log(arr)
                    return i+1
                }        
        }
        }
        console.log(countNum(10))
    }复制代码

题一只要把思路相对了其实不难,上面的解法也相对简单,你们应该都能看明白。关于题二,我的以为稍微难点,且看下方分解咯!数组

题二描述:数据结构

食堂有一张靠墙的长桌,规定每一个人必须隔着吃饭,不容许挨着。如今长桌上已经有了一些各自独处得人,来了一些新人,判断他们可否找到位置?
输入一个字符串table,只含有0和1,1表示有人,0表示没有人
输入一个正整型的数n,表示新来就餐的人数
输出一个布尔值,可以安排全部的人,返回false,不然返回true
例子:输入1001,1
那么显然没有位置给新来的一我的,返回false编程语言

情景转移一下,是否是很像幼儿园里小朋友们,排排坐等着老师发果果吃?怕小朋友们起争执,因此小朋友须要间隔来坐。
原谅我看到这道题真的是脑补了一幅好有爱的画面……函数

这个问题的关键无非也就是,“有人”=1,“没人”=0,1跟1之间必须隔着0。
也许不少人刚看到题目会想着去找间隔,把0变成1,好吧,我也是这样。
可是这样立刻就本身也把本身绕晕了。其实咱们不必定要去动这个字符串,换个视野,把这道题当作计数的问题是否是SO EASY?post

建模对于编程是如此的重要!
建模对于编程是如此的重要!
建模对于编程是如此的重要!

重要的事情说多少遍都不嫌多,算法题尤为要注意建模思路,
找对思路很简单,要是跑偏了就别提多痛苦,
若是此时的你也正在被一轮轮笔试轰炸,我相信你懂!

这道题个人思路是这样的:
一、先把字符串两边的0找出来,是2的倍数则能够坐一我的,好比001,能够坐一我的,0001仍是只能坐一我的,00001能够坐两我的,中间的算法和这个相似,但有所不一样
二、再取中间1**1这样的字符串,遇到一个0则将其计数,当遇到下一个1终止计数
三、这时有一个规律,个数为1,2不能坐人0,3,4能够坐一我的,5,6能够坐两我的。。。依次类推

function isOk(table,n){
        if(n<=0){return true; }            //输入人数为0,直接返回true
        if(typeof table=='string'||table instanceof String){    //判断是不是字符串
            var start=0,end=0,newTable=[],
            arr=table.split(''),length=arr.length
            num=0;
            //start是第一个1的位置,end是最后一个1的位置,newTable是一个新
            //数组,用来存放把两边0截掉后形如1***1这样的字符串
            //num用来临时存放一组0的个数
            for(var i=0;i<length;i++){
                if(arr[i]=='1'){//找出字符串里的第一个“1”
                    start=i    //找到一个1即将索引赋值给start
                    n=n-parseInt(start/2)  //因为0的个数,n减掉部分值
                    break                   //找到一个1就中止循环
                }
            }
            for(var j=length-1;j>0;j--){
                if(arr[j]=='1'){
                    end=j
                    n=n-parseInt((length-1-end)/2)
                    break
                }
            }
            newTable=arr.slice(start,end+1)     //截取掉两边的0后的数组
            newTable.forEach(function(item){
                if(item=='0'){                  //对一组0进行计数
                    num++
                }else if(item=='1'){
                    n=n-parseInt((num-1)/2)     //找全一组后,n减掉部分值
                    num=0                       //并重置num,从新计数
                }
            })
            return n<=0?true:false
            //在循环外面判断,n是否被减完了,为了下降某些状况下的遍历次数
            //也能够在每次n减完后立刻判断n是否小于0,是否须要停止整个操
            //做,这种在给定的n比较小的时候能大大下降遍历次数
        }else{
            return true;
        }
    }复制代码

好辣,排排坐如今也作好了!

总归来讲呢,小米的校招知识广度仍是有的,除了前端专业知识,算法、操做系统、数据结构、智商情商都有涉及,前面被BAT虐了以后,作完小米的题居然会以为学长的店仍是些许温柔的,说不定有戏哈哈。

关于上面两道题,欢迎你们有好的思路跟我讨论,其实我都很差意思说这两套解法已是我通过了几个小时琢磨后的成果了。考试毕竟跟平时的心态会有变化,尤为是我一紧张脑子就很差使,有好的面经笔经还望各位不吝赐教辣,小女子在此谢过!
附掘金秋招征文大赛连接

相关文章
相关标签/搜索