小米筆試:「楊輝三角」&「排排坐吃果果」|掘金技術徵文

或許每個武大的學生,都會對小米有不同的情懷吧。
畢竟雷軍做爲武大傑出校友已經名滿天下,創業經歷也足夠勵志傳奇,對學校的情懷也是特別吸粉的一點。
今年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虐了以後,作完小米的題居然會以爲學長的店仍是些許溫柔的,說不定有戲哈哈。

關於上面兩道題,歡迎你們有好的思路跟我討論,其實我都很差意思說這兩套解法已是我通過了幾個小時琢磨後的成果了。考試畢竟跟平時的心態會有變化,尤爲是我一緊張腦子就很差使,有好的面經筆經還望各位不吝賜教辣,小女子在此謝過!
附掘金秋招徵文大賽連接

相關文章
相關標籤/搜索